I have some strange behaviour, at least for me, that is causing me some bugs in my project.
I am using Django 1.9 and a third party django package (django-jet) that makes usage of field.related_model
property in Django admin and sometimes it fails because it expects field.related_model
returns a model instance and for some of my models is returning the model name.
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
Things that I tried:
- If Django's related_model is a @property instead a @cached_property it works and returns the model instance.
- If I call
field.remote_field.model
instead offield.related_model
in the line that is causing the bug it works and returns the model instance.
Please, do you have any idea? I can make the workaround but I would like to know why this behaviour.
Thanks in advance!
I think the problem here arises because jet is trying to use
related_model
in theRelatedFieldAjaxListFilter.field_choices()
method, and this may executed before all apps have been loaded. If I understand correctly, therelated_model
value is initially a string, which is replaced with a model object in the course of model initialization. If you try to get that value before the apps have all loaded, you may get either a string or an object, depending on the order in which the models are loaded. And, since it's a cached property, getting a string value at that stage would cause the string value to be cached. See, for example, the comment indjango.db.models.options
,By making
related_name
an uncached property, you avoid that issue.In the
django.contrib.admin.filters.RelatedFieldListFilter
code, they do NOT userelated_model
to get the model object, but instead use a utility function,django.contrib.admin.utils.get_model_from_relation()
. TheRelatedFieldAjaxListFilter.field_choices()
should probably be doing something similar.