在 Django 中,给定一个模型实例,如何确定foreignkey字段是否已完全水合?

Zac*_*c B 0 python django orm caching foreign-keys

语境:

我维护遗留的 Django 代码。在许多情况下,我的代码接收多个模型对象,每个模型对象都有一个ForeignKey或代表相同数据实体的手动缓存属性。因此所涉及的数据实体不会改变。但是,并非我收到的所有对象都曾经访问过这些foreignkey字段或缓存的属性,因此数据可能不会出现在这些对象上,尽管它会在第一次访问时延迟加载。

我不容易访问/控制声明模型的代码。

我想找到我拥有的任何一个具有已准备好的缓存的对象,这样我就可以避免访问数据库来检索我想要的数据(如果没有,我会在必要时这样做)。这是因为该数据的获取过于频繁,导致性能问题。

Django 1.6,Python 2.7。

问题

我可以询问我们手动缓存的字段,并且internal_is_cached(instance, 'fieldname')无需运行查询。但是,我无法对ForeignKey字段执行此操作。

假设我在 Django 中有一个模型类,Foo如下所示:

class Foo(models.Model):
    bar = models.ForeignKey('BarModel')
Run Code Online (Sandbox Code Playgroud)

问题

Foo如果我从某处获取模型的实例,但我不知道是否bar曾经调用过它,或者是否已急切地获取它,我如何确定读取instance.bar是否会查询数据库?

换句话说,我想从外部确定任意模型是否具有针对给定的内部缓存ForeignKey,而关于该模型的状态或来源的其他知识为零。

我尝试过的

  • 我尝试使用 Django 缓存进行模型缓存来解决该问题。相关数据的获取过于频繁,以至于对我们的缓存系统造成了不可持续的负载。

  • 我从这个问题尝试了各种解决方案。它们适用于修改后的模型,但似乎不适用于尚未突变的模型——我对模型的“延迟加载”状态感兴趣,而不是“待修改”状态。其中许多解决方案也不适用,因为它们需要更改模型继承或行为,我希望尽可能避免这种情况(政治)。

  • 这个问题看起来很有希望,但它需要控制模型的初始读者过程。我的代码接收到的模型对象可以来自任何地方。

    • 在测试中,对[本文]中描述的事后缓存启动进行相反的操作对我有用。然而,它依赖于_default_manager模型对象的内部方法,众所周知,这对于我们在生产中的一些(高度定制的)模型对象来说是不准确的字段引用。其中一些非常奇怪,如果可能的话,我更愿意坚持使用记录的(或者至少是稳定的并且不经常被绕过的)API。

Cyr*_*lop 5

感谢 @Daniel Roseman的澄清。

使用 Django 版本 <= 1.6 (您的情况下的工作解决方案)
您可以检查您是否foo_instance有一个_bar_cache属性:

hasattr(foo_instance, "_bar_cache")
Run Code Online (Sandbox Code Playgroud)

就像这里解释的那样。

Django 版本 > 1.6
缓存的字段现在存储在属性fields_cache的字典中_state

foo_instance._state.fields_cache["bar"]
Run Code Online (Sandbox Code Playgroud)