2011-02-03 74 views
94

在Django中,你可以指定喜歡的關係:Django:從字符串獲取模型?

author = ForeignKey('Person') 

,然後在內部它有字符串「人」轉換成模型Person

這是幹什麼的功能?我想用它,但我找不到它。

回答

146

作爲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): 
+8

此解決方案在Django 1.7中已棄用,請參閱此解決方案的其他答案:http://stackoverflow.com/a/26126935/155987 – 2015-06-30 22:26:22

+2

嗨@mpen,我建議您更新您的答案。 [在django 1.9上get_model在AppConfig上定義](https://docs.djangoproject.com/es/1.9/ref/applications/#django.apps.AppConfig.get_model):`from django.apps import AppConfig` – danihp 2016-04-20 14:18:03

+0

@danihp謝謝,補充說明。 – mpen 2016-04-20 21:24:53

3

我不確定它在Django中的位置,但可以這樣做。

通過反射將類名映射到字符串。

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

是否clls .__類__.__ name__或只是clls .__ name__? – 2017-07-25 12:08:22

30

大多數模型 「串」 出現的形式是 「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」格式,上面的兩個班輪將工作。

13

只是任何人都陷入(像我一樣):

from django.apps import apps 

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

app_name應使用引號上市,也應model_name(即不要試圖將其導入)

get_model接受小寫或大寫「模型名稱」

97

作爲Django的1.7的django.db.models.loadingis deprecated贊成新的應用程序加載系統(將在1.9移除)。該1.7 docs give us的,而不是以下:每tttthomasssss評論

$ python manage.py shell 
Python 2.7.6 (default, Mar 5 2014, 10:59:47) 
>>> from django.apps import apps 
>>> User = apps.get_model(app_label='auth', model_name='User') 
>>> print User 
<class 'django.contrib.auth.models.User'> 
>>> 

編輯。

15

在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 
5

如果你不知道在哪個應用程序您的模型存在,你可以這樣搜索:

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

請記住,your_model_name必須是小寫。

1

這裏是一個不太具體的Django的方法來從字符串獲取類:

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

,或者您可以使用導入庫,如圖here

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