Python 将模型名称作为字符串传递的最佳实践

Python 将模型名称作为字符串传递的最佳实践,python,django,django-views,django-context,Python,Django,Django Views,Django Context,我有两个不同的模型,我希望在不同的时间通过公共字段名进行类似的过滤,因此我编写了一个上下文函数,通过将字符串作为参数用作模型名来处理这两个模型。现在我正在使用eval(),但直觉告诉我这是一个严重的错误。有没有比我描述的更像蟒蛇的方式 下面是我的代码目前的简略版本: def reference_context(model, value): menu = main_menu() info = company_info() pages = get_list_or_404(ev

我有两个不同的模型,我希望在不同的时间通过公共字段名进行类似的过滤,因此我编写了一个上下文函数,通过将字符串作为参数用作模型名来处理这两个模型。现在我正在使用eval(),但直觉告诉我这是一个严重的错误。有没有比我描述的更像蟒蛇的方式

下面是我的代码目前的简略版本:

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)

欢迎并大力鼓励对任何其他问题进行评论。

如果它们来自同一模块(
models.py
),您可以使用
getattr
检索模型类,并使用
kwargs
(带双星号的dict)以这种方式:

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})

如果它们来自同一个模块(
models.py
),则可以使用
getattr
检索模型类,并使用
kwargs
(带双星号的dict)以这种方式:

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})

您可以使用
get_model
实用程序功能,该功能采用应用程序名称和型号名称

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

您可以使用
get_model
实用程序功能,该功能采用应用程序名称和型号名称

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

我真的不明白为什么需要将模型作为字符串传递—只需传递模型引用即可。例如

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")

正如我在评论中解释的,如果您真的需要将字符串映射到模型,请使用显式注册表/映射。这可以防止人们操纵表单数据,从而允许他们创建一个用户,而不是一本“书”:


我真的不明白为什么需要将模型作为字符串传递—只需传递模型引用即可。例如

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")

正如我在评论中解释的,如果您真的需要将字符串映射到模型,请使用显式注册表/映射。这可以防止人们操纵表单数据,从而允许他们创建一个用户,而不是一本“书”:


为什么需要将模型作为字符串而不是引用传递?例如,据我所知,引用上下文(MyModel、value)并不常见。在这种情况下,我会创建自己的显式名称注册->模型(一个简单的dict就可以)并使用它。这样,当有人在表单中注入“User”作为模型时,可以避免意外的安全问题。为什么需要将模型作为字符串而不是引用传递?例如,据我所知,引用上下文(MyModel、value)并不常见。在这种情况下,我会创建自己的显式名称注册->模型(一个简单的dict就可以)并使用它。这样,当有人在表单中注入“用户”作为模型时,可以避免意外的安全问题。