Django:从字符串中获取模型?

mpe*_*pen 123 django django-models

在Django中,您可以指定以下关系:

author = ForeignKey('Person')
Run Code Online (Sandbox Code Playgroud)

然后在内部它必须将字符串"Person"转换为模型Person.

这样做的功能在哪里?我想用它,但我找不到它.

mpe*_*pen 160

从Django 1.9开始,方法是django.apps.AppConfig.get_model(model_name).
- danihp


从Django 1.7开始,django.db.models.loading不赞成使用新的应用程序加载系统(将在1.9中删除).
- 斯科特伍德尔


找到了.它在这里定义:

from django.db.models.loading import get_model
Run Code Online (Sandbox Code Playgroud)

定义为:

def get_model(self, app_label, model_name, seed_cache=True):
Run Code Online (Sandbox Code Playgroud)

  • 在Django 1.7中不推荐使用此解决方案,请参阅此解决方案的其他答案:http://stackoverflow.com/a/26126935/155987 (11认同)
  • 最新(2020)解决方案:`from django.apps import apps`然后:`apps.get_model('app_name', 'Model')` /sf/ask/2691053991/名称获取型号 (8认同)
  • 嗨@mpen,我建议你更新你的答案.[关于django 1.9 get_model在AppConfig上定义](https://docs.djangoproject.com/es/1.9/ref/applications/#django.apps.AppConfig.get_model):`来自django.apps import AppConfig` (4认同)
  • 在Django 1.7+中,最好在Django应用程序注册表上使用get_model(),可通过`django.apps.apps.get_model(model_name)`获得。AppConfig对象有不同的用途,需要您创建一个AppConfig实例才能调用“ get_model()”。 (2认同)
  • Django 1.11需要@luke_aus提供的答案 (2认同)

Sco*_*all 124

从Django 1.7开始,django.db.models.loading 不赞成使用新的应用程序加载系统(将在1.9中删除).该1.7文档给我们,而不是执行以下操作:

>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'django.contrib.auth.models.User'>
Run Code Online (Sandbox Code Playgroud)

根据tttthomasssss编辑评论.

  • 可选形式 `apps.get_model("appName.ModelName")` (5认同)

luk*_*aus 54

只为任何人卡住(就像我做的那样):

from django.apps import apps

model = apps.get_model('app_name', 'model_name')
Run Code Online (Sandbox Code Playgroud)

app_name应该使用引号列出,应该model_name(即不要尝试导入它)

get_model 接受小写或大写'model_name'


Ch'*_*arr 32

大多数模型"字符串"显示为"appname.modelname"形式,因此您可能希望在get_model上使用此变体

from django.db.models.loading import get_model

your_model = get_model ( *your_string.split('.',1) )
Run Code Online (Sandbox Code Playgroud)

django代码中通常将这些字符串转换为模型的部分稍微复杂一点来自django/db/models/fields/related.py:

    try:
        app_label, model_name = relation.split(".")
    except ValueError:
        # If we can't split, assume a model in current app
        app_label = cls._meta.app_label
        model_name = relation
    except AttributeError:
        # If it doesn't have a split it's actually a model class
        app_label = relation._meta.app_label
        model_name = relation._meta.object_name

# Try to look up the related model, and if it's already loaded resolve the
# string right away. If get_model returns None, it means that the related
# model isn't loaded yet, so we need to pend the relation until the class
# is prepared.
model = get_model(app_label, model_name,
                  seed_cache=False, only_installed=False)
Run Code Online (Sandbox Code Playgroud)

对我来说,这似乎是将其分解为核心代码中的单个函数的好例子.但是,如果您知道您的字符串是"App.Model"格式,则上面的两个衬垫将起作用.

  • 我认为第二行应该是:`your_model = get_model(*your_string.rsplit('.',1))`.App标签有时是点状格式,但型号名称始终是有效标识符. (3认同)

Cra*_*enz 15

在Django 1.7+中这样做的有福方式是:

import django
model_cls = django.apps.apps.get_model('app_name', 'model_name')
Run Code Online (Sandbox Code Playgroud)

因此,在所有框架教程的规范示例中:

import django
entry_cls = django.apps.apps.get_model('blog', 'entry')  # Case insensitive
Run Code Online (Sandbox Code Playgroud)


Wil*_*ams 11

2020年解决方案:

from django.apps import apps

apps.get_model('app_name', 'Model')
Run Code Online (Sandbox Code Playgroud)

根据您的例如:

apps.get_model('people', 'Person')
Run Code Online (Sandbox Code Playgroud)

per: 导入错误:无法导入名称 get_model


Ola*_*Van 9

如果您不知道模型存在于哪个应用程序中,您可以这样搜索:

from django.contrib.contenttypes.models import ContentType 
ct = ContentType.objects.get(model='your_model_name') 
model = ct.model_class()
Run Code Online (Sandbox Code Playgroud)

请记住,your_model_name必须为小写.


Gly*_*ine 5

另一个为懒人提供更少代码的演绎。在 Django 2+ 中测试

from django.apps import apps
model = apps.get_model("appname.ModelName") # e.g "accounts.User"
Run Code Online (Sandbox Code Playgroud)