Django:从字符串获取模型?

Django:从字符串获取模型?,django,django-models,Django,Django Models,在Django中,可以指定如下关系: author = ForeignKey('Person') 然后它必须在内部将字符串“Person”转换为模型Person 做这个的函数在哪里?我想用它,但我找不到。我不确定它在Django的什么地方做的,但你可以这样做 通过反射将类名映射到字符串 classes = [Person,Child,Parent] def find_class(name): for clls in classes: if clls.__class__.__name__

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

author = ForeignKey('Person')
然后它必须在内部将字符串“Person”转换为模型
Person


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

我不确定它在Django的什么地方做的,但你可以这样做

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

classes = [Person,Child,Parent]
def find_class(name):
 for clls in classes:
  if clls.__class__.__name__ == name:
   return clls
从Django 3.0开始,它是

从Django 1.9开始,该方法为。
--

从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.modelname”的形式出现,因此您可能希望在get\u模型上使用此变体

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.Model”格式,则上面的两行代码可以使用。

仅适用于任何卡住的人(就像我所做的那样):

app\u name
应使用引号列出,就像
model\u name
一样(即不要尝试导入它)


get\u model
接受小写或大写的“model\u name”

django.db.models.loading
was()支持新的

Django向我们提供以下信息:

>>> from django.apps import apps
>>> User = apps.get_model(app_label='auth', model_name='User')
>>> print(User)
<class 'django.contrib.auth.models.User'>
>>从django.apps导入应用程序
>>>User=apps.get\u model(app\u label='auth',model\u name='User')
>>>打印(用户)

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

导入django model\u cls=django.apps.apps.get\u model('app\u name','model\u name')) 因此,在所有框架教程的规范示例中:

导入django entry_cls=django.apps.apps.get_model('blog','entry')#不区分大小写
如果您不知道您的模型存在于哪个应用程序中,您可以通过以下方式进行搜索:

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

请记住,您的_model_名称必须是小写的。

这里有一种不太适合django的方法,可以从字符串中获取类:

mymodels = ['ModelA', 'ModelB']
model_list = __import__('<appname>.models', fromlist=mymodels)
model_a = getattr(model_list, 'ModelA')
mymodels=['ModelA','ModelB']
模型列表=uuu导入('):

导入导入库
myapp_models=importlib.import_模块(“.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')
per:

我认为第二行应该是:
你的_model=get_model(*你的_string.rsplit('.',1))
。应用程序标签有时是点格式,但是模型名称始终是一个有效的标识符。看起来这在新的
应用程序中是不必要的。get_model
。作为一种快捷方式,此方法还接受一个参数,格式为
app\u label.model\u name
。“此解决方案在Django 1.7中已被弃用,请参阅此解决方案的另一个答案:Hi@mpen,我建议您更新您的答案。:
从Django.apps导入AppConfig
Django.apps.AppConfig是一个生成器类型,不能像模型对象那样工作。在Django 1.7+中,最好使用get\u model()在Django应用程序注册表上,该注册表可通过
Django.apps.apps.get_model(model_name)
访问。AppConfig对象的用途不同,需要创建AppConfig实例才能调用
get_model()
。Django 1.11需要@luke_ausI提供的答案,该答案用于使用pydoc的“locate”函数…不确定这里的区别,但为了保持在Django中,我已经切换到这个方法。谢谢。是clls.\uuuuu类\uuuuuuu名\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?
from django.apps import apps

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