为什么Django的related_model属性返回字符串而不是Model实例?

Die*_*rro 7 python django django-admin django-jet

我有一些奇怪的行为,至少对我而言,这会导致我的项目中出现一些错误.

我正在使用Django 1.9和第三方django包(django-jet),它field.related_model在Django admin中使用属性,有时它失败,因为它期望field.related_model返回一个模型实例,并且我的一些模型返回模型名称.

这是Django代码中定义的属性:

@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
Run Code Online (Sandbox Code Playgroud)

我试过的事情:

  • 如果Django的related_model是@property而不是@cached_property它的工作原理,并返回模型实例.
  • 如果我调用field.remote_field.model而不是field.related_model在导致错误的行中调用它并返回模型实例.

拜托,你有什么想法吗?我可以做出解决方法,但我想知道为什么会出现这种情况.

提前致谢!

mol*_*ule 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.
Run Code Online (Sandbox Code Playgroud)

通过创建related_name未缓存的属性,您可以避免该问题。

django.contrib.admin.filters.RelatedFieldListFilter代码中,他们不使用related_model获取模型对象,而是使用实用程序函数django.contrib.admin.utils.get_model_from_relation(). 他们RelatedFieldAjaxListFilter.field_choices()可能应该做类似的事情。