2016-03-02 36 views
7

Mam dziwne zachowanie, przynajmniej dla mnie, które powoduje pewne błędy w moim projekcie.Dlaczego właściwość related_model produktu Django zwraca łańcuch zamiast instancji Model?

Używam Django 1.9 i pakiet osoba trzecia django (django-jet) sprawia, że ​​wykorzystanie field.related_model nieruchomości w Django administratora, a czasem nie udaje, ponieważ oczekuje field.related_model powraca instancji modelu i dla niektórych z moich modeli wraca nazwę modelu .

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 

Rzeczy, które próbowałem:

  • Jeśli related_model Django jest @property zamiast tego @cached_property to działa i zwraca instancję modelu.
  • Jeśli zadzwonię pod numer field.remote_field.model zamiast field.related_model w linii, która powoduje błąd, działa i zwraca instancję modelu.

Proszę, masz jakiś pomysł? Mogę zrobić obejście, ale chciałbym wiedzieć, dlaczego to zachowanie.

Z góry dziękuję!

Odpowiedz

2

Myślę, że problem tutaj powstaje, ponieważ jet próbuje użyć metody related_model w metodzie RelatedFieldAjaxListFilter.field_choices(), co może zostać wykonane przed załadowaniem wszystkich aplikacji. Jeśli dobrze rozumiem, wartość related_model jest początkowo łańcuchem, który jest zastępowany obiektem modelu podczas inicjowania modelu. Jeśli spróbujesz uzyskać tę wartość przed załadowaniem wszystkich aplikacji, możesz otrzymać ciąg lub obiekt, w zależności od kolejności ładowania modeli. A ponieważ jest to właściwość buforowana, pobranie wartości ciągu na tym etapie spowodowałoby buforowanie wartości ciągu. Patrz, na przykład, komentarz w 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. 

Dokonując related_name właściwość niebuforowanych można uniknąć tego problemu.

W kodzie django.contrib.admin.filters.RelatedFieldListFilter NIE używają related_model do pobierania obiektu modelu, ale zamiast tego używają funkcji użytecznej, django.contrib.admin.utils.get_model_from_relation(). RelatedFieldAjaxListFilter.field_choices() prawdopodobnie powinien robić coś podobnego.