姜戈: 从字符串中得到模型?

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

author = ForeignKey('Person')

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

这个函数在哪里? 我想用它,但找不到。

102608 次浏览

我不知道姜戈哪里做的,但你可以做到这一点。

通过反射将类名映射到字符串。

classes = [Person,Child,Parent]
def find_class(name):
for clls in classes:
if clls.__class__.__name__ == name:
return clls

从 Django 1.114.0(至少) ,是 AppConfig.get_model(model_name, require_ready=True)

在 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

定义为:

def get_model(self, app_label, model_name, seed_cache=True):

大多数模型“字符串”以“ appname.model name”的形式出现,因此您可能希望在 get _ model 上使用这个变体

from django.db.models.loading import get_model


your_model = get_model ( *your_string.split('.',1) )

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)

对我来说,这似乎是一个很好的例子,可以将其分解为核心代码中的一个函数。但是,如果您知道您的字符串在“ App”中。“模型”格式,上面的两行就可以工作了。

只是为了那些被困住的人(就像我一样) :

from django.apps import apps


model = apps.get_model('app_name', 'model_name')

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

get_model接受小写或大写的“ model _ name”

django.db.models.loading在 Django 1.7已经废弃了(1.9秒内移除) ,有利于新的 应用程序加载系统应用程序加载系统

Django 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'>

在 Django 1.7 + 中实现这一点的最好方法是:

import django
model_cls = django.apps.apps.get_model('app_name', 'model_name')

因此,在所有框架教程的典型例子中:

import django
entry_cls = django.apps.apps.get_model('blog', 'entry')  # Case insensitive

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

from django.contrib.contenttypes.models import ContentType
ct = ContentType.objects.get(model='your_model_name')
model = ct.model_class()

请记住,your _ model _ name 必须是小写。

下面是从 string 获取类的一种不太特定于 django 的方法:

mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')

或者你可以使用如 给你所示的 import lib:

import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')

另一个用于懒人的代码更少的版本,在 Django 2 + 中进行了测试

from django.apps import apps
model = apps.get_model("appname.ModelName") # e.g "accounts.User"

2020年解决方案:

from django.apps import apps


apps.get_model('app_name', 'Model')

根据你的例子:

apps.get_model('people', 'Person')

按: 导入错误: 无法导入名称 get _ model