2016-03-02 2 views
7

У меня есть странное поведение, по крайней мере для меня, это вызывает у меня некоторые ошибки в моем проекте.Почему свойство related_model Django возвращает строку вместо экземпляра модели?

Я использую Django 1.9 и пакет третьей стороны Джанго (django-jet), что делает использование field.related_model собственности в Django администратора и иногда это не удается, потому что он ожидает, что field.related_model возвращает экземпляр модели и некоторые из моих моделей возвращается название модели ,

This is the property defined in Django code:

@cached_property 
def related_model(self): 
    # Can't cache this property until all the models are loaded. 
    apps.check_models_ready() 
    return self.remote_field.model 

Вещи, которые я пытался:

  • Если related_model Джанго является @property вместо этого @cached_property он работает и возвращает экземпляр модели.
  • Если я вызываю field.remote_field.model вместо field.related_model в строке, которая вызывает ошибку, она работает и возвращает экземпляр модели.

Возможно, у вас есть идеи? Я могу сделать обходной путь, но я хотел бы знать, почему это поведение.

Заранее благодарен!

ответ

2

Я думаю, проблема здесь возникает из-за того, что jet пытается использовать related_model в методе RelatedFieldAjaxListFilter.field_choices(), и это может быть выполнено до того, как все приложения будут загружены. Если я правильно понимаю, значение related_model изначально представляет собой строку, которая заменяется модельным объектом в ходе инициализации модели. Если вы попытаетесь получить это значение до того, как все приложения будут загружены, вы можете получить строку или объект в зависимости от порядка загрузки моделей. И поскольку это свойство кэширования, получение строкового значения на этом этапе приведет к кэшированию строкового значения. Смотрите, например, комментарий в django.db.models.options,

# The mechanism for getting at the related model is slightly odd - 
# ideally, we'd just ask for field.related_model. However, related_model 
# is a cached property, and all the models haven't been loaded yet, so 
# we need to make sure we don't cache a string reference. 

Делая related_name некэшированные собственности, избежать этой проблемы.

В коде django.contrib.admin.filters.RelatedFieldListFilter они НЕ используют related_model для получения объекта модели, но вместо этого используют служебную функцию django.contrib.admin.utils.get_model_from_relation(). Вероятно, RelatedFieldAjaxListFilter.field_choices() должен делать что-то подобное.