我有两个不同的模型,我想在不同的时间通过公共字段名称进行类似的过滤,所以我编写了一个上下文函数,通过将字符串作为参数用作模型名称来处理两个模型。现在我正在使用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 :(得分:1)
如果它们来自同一个模块(models.py
),您可以使用getattr
来检索模型类,并使用kwargs
(带双星号的dict)这样:< / p>
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 :(得分:1)
您可以使用get_model
实用程序功能,该功能获取应用名称和型号名称。
from django.db.models import get_model
User = get_model("auth", "User") # returns django.contrib.auth.models.User
答案 2 :(得分:1)
我真的不明白为什么你需要将模型作为字符串传递 - 只需传递模型参考。 E.g。
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], ...)