【问题标题】:Does a django query save its result after it's been called?django 查询是否会在调用后保存其结果?
【发布时间】:2010-12-03 01:40:26
【问题描述】:

我正在尝试确定一个简单的缓存技巧是否真的有用。我知道 Django 查询集懒于提高效率,但我想知道它们是否在调用数据后保存查询结果。

例如,如果我有两个模型:


class Klass1(models.Model):  
    k2 = models.ForeignKey('Klass2')

class Klass2(models.Model):
    # Model Code ...
    @property
    def klasses(self):
        self.klasses = Klass1.objects.filter(k2=self)
        return self.klasses

然后我在某处调用klass_2_instance.klasses[:],然后访问数据库并返回一个查询。我想知道如果我再次调用klass_2_instance.klasses,数据库会被第二次访问,还是django查询会保存第一次调用的结果?

【问题讨论】:

  • 我有没有提到 klass 而不是 class 看起来很糟糕?如果在 class 会导致错误的上下文中使用名称,则 cls 是 IMO 的方式。
  • 不用担心,我只是在这里使用了 klass 作为任意名称。这不是我使用的实际模型,只是示例代码。

标签: python django django-models django-queryset


【解决方案1】:

Django 不会为你缓存它。

您可以只执行 self.klass1_set.all(),而不是 Klass1.objects.filter(k2=self)。 因为 Django 总是在 1-n 关系的多方中创建一个集合。

我猜这种缓存很复杂,因为它应该记住所有使用的过滤器、排除和 order_by。尽管可以使用任何设计良好的哈希来完成,但您至少应该有一个禁用缓存的参数。

如果你想要任何缓存,你可以这样做:

类 Klass2(模型。模型): def __init__(self, *args, **kwargs): self._klass1_cache = 无 super(Klass2, self).__init__(*args, **kwargs) 定义类(自我): 如果 self._klass1_cache 为无: # 这里你不能删除 list(..) 因为它强制查询执行一次。 self._klass1_cache = list(self.klass1_set.all()) 返回 self._klass1_cache

当您在所有相关对象中循环多次时,这非常有用。对我来说,它经常发生在模板中,当我需要循环不止一次时。

【讨论】:

    【解决方案2】:

    这个查询没有被 Django 缓存。

    forwards FK 关系 - 即给定 Klass 对象 klass,执行 klass.k2 - 在第一次查找后缓存。但是反过来,你在这里做的——实际上通常拼写为klass2.klass_set.all()——是缓存的。

    您可以轻松记住它:

    @property
    def klasses(self):
        if not hasattr(self, '_klasses'):
            self._klasses = self.klass_set.all()
        return self._klasses
    

    (请注意,您现有的代码将不起作用,因为您正在使用属性覆盖方法 klasses。)

    【讨论】:

    • 有趣的是,由于我使用的是属性装饰器,它确实有效。 Python 假设我将数据放入变量klasses,并将对修饰方法的引用替换为对新值的引用。但是,就像您说的那样,在这种情况下实际上不会缓存数据。
    【解决方案3】:

    如果您想要查询集的透明缓存,请尝试使用 johnny-cache。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-11
      • 2011-06-05
      • 2021-04-19
      • 1970-01-01
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2014-01-13
      相关资源
      最近更新 更多