【问题标题】:How do I retrieve a Django model class dynamically?如何动态检索 Django 模型类?
【发布时间】:2010-09-29 12:50:39
【问题描述】:

如果没有 Django 模型的完整模块路径,是否可以执行以下操作:

model = 'User' [in Django namespace]
model.objects.all()

...相对于:

User.objects.all().

编辑:我正在尝试根据命令行输入进行此调用。是否可以避免导入语句,例如,

model = django.authx.models.User

没有 Django 返回错误:

"global name django is not defined."

【问题讨论】:

    标签: python django django-models django-queryset


    【解决方案1】:

    我想你正在寻找这个:

    from django.db.models.loading import get_model
    model = get_model('app_name', 'model_name')
    

    当然还有其他方法,但如果您不知道需要将哪些模型文件导入命名空间,我会采用这种方法。 (请注意,如果不首先知道它属于哪个应用程序,实际上没有办法安全地获取模型。如果您想测试您在迭代所有应用程序模型时的运气,请查看 loading.py 的源代码。)

    Django 1.7+ 的更新: 根据 Django 的 deprecation timelinedjango.db.models.loading 在 Django 1.7 中已被弃用,并将在 Django 1.9 中删除。正如Alasdair's answer 中指出的那样, 在 Django 1.7+ 中,有一个 applications registry。可以使用apps.get_model方法动态获取模型:

    from django.apps import apps
    MyModel = apps.get_model('app_label', 'MyModel')
    

    【讨论】:

    • 回想起来,我认为他也在寻找这个。
    • 所有这些都是有用的答案(我的问题可以通过多种方式解决),但这个最直接解决了我正在寻找的问题。
    【解决方案2】:

    对于 Django 1.7+,有一个 applications registry。可以使用apps.get_model方法动态获取模型。

    from django.apps import apps
    MyModel = apps.get_model('app_label', 'MyModel')
    

    【讨论】:

    • 现在django.db.models.loading 已经成为deprecated in Django 1.9,这可能是在Django 中动态加载模型的最佳方法。
    • 糟糕,django.db.models.loading 实际上已在 1.7 中弃用并在 1.9 中删除。感谢@Alasdair 在对accepted answer 的编辑中澄清这一点。
    • 循环引用冲突的救命稻草解决方案。
    • 这应该是公认的答案,因为 django.db.models.loading 在 Django 1.9 中已弃用:github.com/django/django/blob/…
    • 是否也有类似的方法来选择 ModelForms ?
    【解决方案3】:

    类是 Python 中的“第一类”对象,这意味着它们可以像所有其他对象一样被传递和操作。

    模型是类——您可以从使用类语句创建新模型这一事实中看出:

    class Person(models.Model):
        last_name = models.CharField(max_length=64)
    
    class AnthropomorphicBear(models.Model):
        last_name = models.CharField(max_length=64)
    

    PersonAnthropomorphicBear 标识符都绑定到 Django 类,因此您可以传递它们。如果您想创建在模型级别工作的辅助函数(并共享一个通用接口),这将非常有用:

    def print_obj_by_last_name(model, last_name):
        model_name = model.__name__
        matches = model.objects.filter(last_name=last_name).all()
        print('{0}: {1!r}'.format(model_name, matches))
    

    所以print_obj_by_last_name 将适用于PersonAnthropomorphicBear 模型。只需像这样传递模型:

    print_obj_by_last_name(model=Person, last_name='Dole')
    print_obj_by_last_name(model=AnthropomorphicBear, last_name='Fozzy')
    

    【讨论】:

      【解决方案4】:

      model = django.authx.models.User

      ? Django 返回一个错误,“全局 名称 django 未定义。”

      Django 不返回错误。 Python 可以。

      首先,您必须导入模型。您必须使用

      from django.authx.models import User
      

      其次,如果出现django 未定义的错误,则说明 Django 未正确安装。您必须在 PYTHONPATH 上安装 Django 或安装在 Python lib/site-packages 中。

      要正确安装 Django,请参阅http://docs.djangoproject.com/en/dev/intro/install/#intro-install

      【讨论】:

        【解决方案5】:

        如果您将模型名称作为字符串传递,我想一种方法可能是

        modelname = "User"
        model = globals()[modelname]
        

        但是在某些情况下使用 globals() 可能有点危险。所以要小心处理:)

        【讨论】:

        • 我没有对你投反对票,但我认为大多数人都反对全局变量——尤其是在像 Django 这样的上下文中,这意味着它背后可能有一些大而重要的东西。
        【解决方案6】:
        from django.authx.models import User
        model = User
        model.objects.all()
        

        【讨论】:

          猜你喜欢
          • 2015-04-07
          • 1970-01-01
          • 2015-11-12
          • 1970-01-01
          • 2013-08-04
          • 1970-01-01
          • 2021-10-10
          • 1970-01-01
          • 2017-12-20
          相关资源
          最近更新 更多