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

时间:2011-02-03 00:41:27

标签: django

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

author = ForeignKey('Person')

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

执行此操作的功能在哪里?我想用它,但我找不到它。

9 个答案:

答案 0 :(得分:156)

  

自Django 1.9起,该方法为django.apps.AppConfig.get_model(model_name)    - danihp


  

自Django 1.7起,django.db.models.loading被弃用(将在1.9中删除),转而支持新的应用程序加载系统。
   - Scott Woodall


找到它。它在这里定义:

from django.db.models.loading import get_model

定义为:

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

答案 1 :(得分:119)

django.db.models.loading deprecated in Django 1.7removed in 1.9)支持新的application loading system

Django 1.7 docs给我们以下代码:

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

答案 2 :(得分:46)

只是为了卡住的人(就像我一样):

from django.apps import apps

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

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

get_model接受小写或大写&#39; model_name&#39;

答案 3 :(得分:33)

大多数模型“字符串”显示为“appname.modelname”形式,因此您可能希望在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.Model”格式,则上面的两个衬垫将起作用。

答案 4 :(得分:15)

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

@Bean
public CronTriggerFactoryBean cronTriggerFactoryBean() {
    CronTriggerFactoryBean factory = new CronTriggerFactoryBean();
    factory.setJobDetail(jobDetailFactoryBean().getObject());
    factory.setStartDelay(3000);
    factory.setCronExpression("0 0/2 * 1/1 * ? *");
    return factory;
}

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

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

答案 5 :(得分:8)

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

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

请记住,your_model_name必须为小写。

答案 6 :(得分:3)

我不确定它在Django中的位置,但你可以这样做。

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

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

答案 7 :(得分:3)

2020解决方案:

from django.apps import apps

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

根据您的示例:

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

每: Import Error :cannot import name get_model

答案 8 :(得分:1)

另一种形式,对延迟者的代码更少。在Django 2+中测试过

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