В чем разница между 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
этого объекта, а затем будет сделан запрос к этой модели с первичным ключом объекта записи.