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:
field.remote_field.model instead of field.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 the RelatedFieldAjaxListFilter.field_choices() method, and this may executed before all apps have been loaded.  If I understand correctly, the related_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 in 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.
By making related_name an uncached property, you avoid that issue.
In the django.contrib.admin.filters.RelatedFieldListFilter code, they do NOT use related_model to get the model object, but instead use a utility function, django.contrib.admin.utils.get_model_from_relation().      The RelatedFieldAjaxListFilter.field_choices() should probably be doing something similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With