2013-09-16 65 views
0

我有兩種不同的模型,我希望在不同的時間使用公共字段名稱進行類似的過濾,所以我編寫了一個單一的上下文函數,通過將字符串作爲字符串用作模型名稱的參數。現在我正在使用eval(),但是我的直覺告訴我這是一個嚴重的錯誤。是否有更多pythonic方式來做我所描述的?將模型名稱作爲字符串傳遞的最佳做法

這裏是我的代碼看起來像此刻一個縮短版:

def reference_context(model, value): 
    menu = main_menu() 
    info = company_info() 
    pages = get_list_or_404(eval(model), category = value) 

其次,有沒有辦法通過以類似的方式關鍵字,這樣我就可以沿着線的東西:

def reference_context(model, category, value): 
    menu = main_menu() 
    info = company_info() 
    pages = get_list_or_404(eval(model), eval(category) = value) 

關於任何其他問題的評論是受歡迎的,也是極大的鼓勵。

+0

爲什麼您需要將模型作爲字符串傳遞而不是作爲參考?例如。 reference_context(MyModel,value) –

+0

據我所知,並不常見。在這種情況下,我會自己明確地註冊名稱 - >模型(一個簡單的字典將會這樣做)並使用它。這樣,當有人在表單中注入「用戶」作爲模型時,可以避免意外的安全問題。 –

回答

1

如果他們是來自同一個模塊(models.py),你可以使用getattr檢索模型類,並kwargs(雙星號的字典)這樣說:

from myapp import models 

def reference_context(model, value): 
    menu = main_menu() 
    info = company_info() 
    pages = get_list_or_404(getattr(models, model), **{category: value}) 
1

可以使用get_model實用程序功能,它採用應用程序名稱和型號名稱。

from django.db.models import get_model 
User = get_model("auth", "User") # returns django.contrib.auth.models.User 
1

我真的不明白爲什麼你需要將模型作爲字符串傳遞 - 只需傳遞模型引用即可。例如。

class ModelA(models.Model): 
    ... 

class ModelB(models.Model): 
    ... 

def reference_context(model, **kw): 
    menu = main_menu() 
    info = company_info() 
    pages = get_list_or_404(model, **kw) 
    # ... 

在此設置中,您可以傳遞任何模型和任何您想要的查詢,例如,

reference_context(ModelA, category="Hello") 

reference_context(ModelB, item__ordered__lte=now) 

正如我在評論解釋,如果你真的需要爲字符串映射到模型,使用顯式註冊表/映射。這樣可以防止人們操縱表單數據,而這些表單數據可能允許他們創建用戶而不是「Book」:

model_map = dict(book=ModelA, magazine=ModelB) 
reference_context(model_map[model_as_string], ...) 
相關問題