Джанго: Получить модель из строки? - PullRequest
118 голосов
/ 03 февраля 2011

В Django вы можете указать отношения как:

author = ForeignKey('Person')

А затем внутренне необходимо преобразовать строку «Персона» в модель Person.

Где функция, которая это делает? Я хочу использовать это, но я не могу найти это.

Ответы [ 8 ]

156 голосов
/ 03 февраля 2011

Начиная с Django 1.9, метод: django.apps.AppConfig.get_model(model_name).
- Данихп


Начиная с 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):
121 голосов
/ 30 сентября 2014

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'>
48 голосов
/ 11 сентября 2014

только для тех, кто застрял (как я):

from django.apps import apps

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

app_name должны быть перечислены в кавычках, как и model_name (т.е. не пытаться импортировать его)

get_model принимает нижний или верхний регистр 'имя_модели'

33 голосов
/ 06 ноября 2012

Большинство "строк" модели отображаются в виде "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», будут работать две строки выше.

15 голосов
/ 24 ноября 2015

Благословенный способ сделать это в 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
9 голосов
/ 27 октября 2016

Если вы не знаете, в каком приложении существует ваша модель, вы можете выполнить поиск следующим образом:

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

Помните, что your_model_name должно быть в нижнем регистре.

3 голосов
/ 03 февраля 2011

Я не уверен, где это делается в Django, но вы можете сделать это.

Отображение имени класса в строку с помощью отражения.

1 голос
/ 05 мая 2017

Вот менее специфичный для django подход для получения класса из строки:

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

или вы можете использовать importlib, как показано здесь :

import importlib
myapp_models = importlib.import_module('<appname>.models')
model_a = getattr(myapp_models, 'ModelA')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...