Django: получить модель из строки?

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

author = ForeignKey('Person')

И затем внутренне он должен преобразовать строку "Лицо" в модель Person.

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

Ответ 1

По состоянию на 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):

Ответ 3

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

from django.apps import apps

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

app_name следует указывать с помощью кавычек, как и model_name (т.е. не пытайтесь импортировать его)

get_model принимает строчный или верхний регистр 'model_name'

Ответ 4

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

Ответ 5

Благословенный способ сделать это в 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

Ответ 6

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

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

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

Ответ 7

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

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

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

Ответ 8

Ниже приведен менее подходящий для 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')

Ответ 9

Еще одна версия с меньшим количеством кода для ленивых. Проверено в Джанго 2+

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