В чем разница между django apps и django contenttype?

В чем разница между django apps и django contenttype в получении моделей, например

from django.apps import apps
model = apps.get_model(app_label=app_label,model_name=model_name)

и

from django.contrib.contenttypes.models import ContentType
model = ContentType.objects.get(app_label=app_label, model = model).model_class()

apps.get_model(…) будет искать модель, хранящуюся в AppConfig, которая соответствует app_name. Действительно, если мы посмотрим на исходный код [GitHub], то увидим:

def get_model(self, app_label, model_name=None, require_ready=True):
    # …
    if require_ready:
        self.check_models_ready()
    else:
        self.check_apps_ready()

    if model_name is None:
        app_label, model_name = app_label.split('.')

    app_config = self.get_app_config(app_label)

    if not require_ready and app_config.models is None:
        app_config.import_models()

    return app_config.get_model(model_name, require_ready=require_ready)

Таким образом, сначала определяется AppConfig, который соответствует app_label, а затем выполняется вызов для получения объекта модели. У AppConfig есть список, в котором хранятся все модели для этого App. Затем используется логика get_model(…) из AppConfig [GitHub]:

def get_model(self, model_name, require_ready=True):
    # …
    if require_ready:
        self.apps.check_models_ready()
    else:
        self.apps.check_apps_ready()
    try:
        return self.models[model_name.lower()]
    except KeyError:
        raise LookupError(
            "App '%s' doesn't have a '%s' model." % (self.label, model_name))

Таким образом, он будет искать модель в словаре и возвращать ссылку на объект этой модели.


Если вы работаете с ContentType, вы фактически сначала делаете запрос к базе данных, чтобы получить соответствующий ContentType. Например, вы можете запросить ContentType по id (что является основной целью типа содержимого: сопоставление первичного ключа с моделью).

После получения ContentType, Django знает имя приложения и имя модели. Затем он сделает вызов apps.get_model(…), о котором мы говорили ранее, и таким образом получит ссылку на нужную модель. Действительно, метод .model_class() реализован как [GitHub]:

def model_class(self):
    # …
    try:
        return apps.get_model(self.app_label, self.model)
    except LookupError:
        return None

Если вы знаете имя приложения и имя модели, то нет смысла работать с ContentType. Тем более, что база данных может запутаться в типах содержимого и вернуть не то, что нужно. Модель ContentType обычно используется для ссылки на конкретную модель в базе данных . Например, с помощью GenericForeignKey [Django-doc], который состоит из пары двух полей: одно ForeignKey, которое ссылается на элемент ContentType, и одно с первичным ключом объекта, на который ссылаются. Если вы обращаетесь к GenericForeignKey объекта модели, то сначала будет получен ContentType этого объекта, а затем будет сделан запрос к этой модели с первичным ключом объекта записи.

Вернуться на верх