有人可以解释为什么覆盖 get_queryset
并通过 self
引用查询集会完全缓存页面吗?我需要等待 5 分钟或更长时间才能显示数据库更新。
我正在尝试将临时值保存到每个对象并将其传递给模板。
在示例 3 中,我的一切都工作得很好,但不太明白我做了什么才能让它工作,所以任何见解都会很棒!
示例 1:缓存几分钟,但 r.css='abc' 工作正常
class AppointmentListView(ListView):
qs = Appointment.objects.prefetch_related('client', 'patients')
def get_queryset(self):
for r in self.qs:
r.css = 'abc' #<-passes temp value to template ok
return self.qs
示例 2:没有缓存问题,但 r.css='abc' 现在不起作用
如果我不包含方法而只是自动调用查询集,则不会立即显示缓存和数据库更新,但我的临时数据不会到达模板。 类 AppointmentListView(ListView):
queryset = Appointment.objects.prefetch_related('client','patients')
for r in queryset:
r.css = 'abc' #<- NOT passed to template
示例 3:没有缓存问题并且 r.css='abc' 工作正常
最后,如果我将所有内容都放入方法中,一切都会正常 - 临时数据到达模板并且没有缓存。
class AppointmentListView(ListView):
def get_queryset(self):
qs = Appointment.objects.prefetch_related('client','patients')
for r in qs:
r.css = 'abc' #<-passes to template ok
return qs
最佳答案
您所看到的行为是 Python 如何评估您的代码。下面是一个简化的示例,解释了您所看到的内容。
import random
class Example1(object):
roll = random.randint(1, 6) # this is evaluated immediately!
def get_roll(self):
return self.roll
ex1 = Example1()
# the call below always returns the same number!
# (until Python re-interprets the class)
ex1.get_roll()
如果您将上面的代码输入 python 解释器,您会发现 ex1.get_roll()
始终返回相同的数字!
Example1.roll
被称为类或静态变量。这些仅在定义类时评估一次。
class Example2(object):
def get_number(self):
roll = random.randint(1,6)
return roll
在示例2
中,每次调用get_roll
方法时都会生成一个新的随机数。
对于您问题中列出的示例:
示例 1
qs
是一个类变量,因此只被评估一次(这就是您看到“缓存”行为的原因)。对 get_queryset
的后续调用将返回与最初计算的相同的 qs
变量。
示例 2
您没有重写get_queryset
,这意味着使用了ListView.get_queryset
实现。
Django 的 ListView.get_queryset
在评估之前复制 queryset
- 这就是为什么你看不到“缓存”。但是,由于复制了查询集,因此 for 循环的效果将被丢弃。
示例3
这通常是编写代码的正确方法。如果您不想看到“缓存”行为,您应该这样编写方法。
关于python - 重写 get_queryset 会导致 ListView 中的缓存问题,其中数据仍然过时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38949071/