Django 查询在被调用后是否保存其结果?

发布于 2024-10-05 22:58:29 字数 489 浏览 1 评论 0原文

我正在尝试确定一个简单的缓存技巧是否真的有用。我知道 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 查询会保存第一次调用的结果?

I'm trying to determine whether or not a simple caching trick will actually be useful. I know Django querysets are lazy to improve efficiency, but I'm wondering if they save the result of their query after the data has been called.

For instance, if I have two models:


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

And I call klass_2_instance.klasses[:] somewhere, then the database is accessed and returns a query. I'm wondering if I call klass_2_instance.klasses again, will the database be accessed a second time, or will the django query save the result from the first call?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

噩梦成真你也成魔 2024-10-12 22:58:29

Django 不会为你缓存它。

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

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

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

class Klass2(models.Model):
  def __init__(self, *args, **kwargs):
    self._klass1_cache = None
    super(Klass2, self).__init__(*args, **kwargs)

  def klasses(self):
    if self._klass1_cache is None:
      # Here you can't remove list(..) because it is forcing query execution exactly once.
      self._klass1_cache = list(self.klass1_set.all())
    return self._klass1_cache

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

Django will not cache it for you.

Instead of Klass1.objects.filter(k2=self), you could just do self.klass1_set.all().
Because Django always create a set in the many side of 1-n relations.

I guess this kind of cache is complicated because it should remember all filters, excludes and order_by used. Although it could be done using any well designed hash, you should at least have a parameter to disable cache.

If you would like any cache, you could do:

class Klass2(models.Model):
  def __init__(self, *args, **kwargs):
    self._klass1_cache = None
    super(Klass2, self).__init__(*args, **kwargs)

  def klasses(self):
    if self._klass1_cache is None:
      # Here you can't remove list(..) because it is forcing query execution exactly once.
      self._klass1_cache = list(self.klass1_set.all())
    return self._klass1_cache

This is very useful when you loop many times in all related objects. For me it often happens in template, when I need to loop more than one time.

彡翼 2024-10-12 22:58:29

Django 不缓存此查询。

转发 FK 关系 - 即给定一个 Klass 对象 klass,执行 klass.k2 - 是< /em> 在第一次查找后缓存。但相反,您在这里所做的 - 实际上通常拼写为 klass2.klass_set.all() - 被缓存。

您可以轻松地记住它:(

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

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

This query isn't cached by Django.

The forwards FK relationship - ie given a Klass object klass, doing klass.k2 - is cached after the first lookup. But the reverse, which you're doing here - and which is actually usually spelled klass2.klass_set.all() - is not cached.

You can easily memoize it:

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

(Note that your existing code won't work, as you're overriding the method klasses with an attribute.)

心清如水 2024-10-12 22:58:29

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

Try using johnny-cache if you want transparent caching of querysets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文