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

时间:2018-07-12 19:36:39

标签: python django caching orm 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')

问题

如果我从某个地方获得了模型Foo的实例,但是我不知道是否曾经bar被调用,或者是否已经被迫获取后,如何确定读取instance.bar是否会查询数据库?

换句话说,我想从外部确定某个模型是否为给定的ForeignKey准备了内部缓存,而对该模型的状态或来源的其他了解为零。

我尝试过的事情

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

  • 我尝试了this question的各种解决方案。它们适用于修改后的模型,但似乎不适用于尚未突变的模型-我对模型的“延迟加载”状态感兴趣,而不对“待处理的修改”状态感兴趣。这些解决方案中的许多解决方案也不适用,因为它们需要更改模型继承或行为,如果可能的话,我想避免这种情况(政治)。

  • This question看起来很有希望,但它需要控制模型初始阅读器过程。我的代码接收的模型对象可能来自任何地方。

    • 进行[此文章]中描述的事后缓存启动的相反操作对我而言适用于测试。但是,它依赖于模型对象的_default_manager内部方法,该方法对于生产中的某些(高度定制)模型对象来说是不准确的字段参考。其中有些很奇怪,如果可能的话,我宁愿坚持使用已记录(或至少稳定且不经常被绕过)的API。

1 个答案:

答案 0 :(得分:3)

感谢@Daniel Roseman的澄清。

使用Django版本<= 1.6(适合您的情况)
您可以检查您的foo_instance是否具有_bar_cache属性:

hasattr(foo_instance, "_bar_cache")

就像解释了here

使用Django版本> 1.6
现在,已缓存的字段存储在fields_cache属性的_state字典中:

foo_instance._state.fields_cache["bar"]