我对Python比较陌生,并且想知道是否有可能在返回结果之前访问Johnny Cache缓存的结果以进行进一步处理。对它运行进一步的查询。
作为一个简化的例子,考虑我们有一个包含数十万个运动结果的表格,每个运动结果按运动分类,例如网球,足球,高尔夫等。一些用户只对足球和足球感兴趣。高尔夫,所以目前我们使用johnny缓存来缓存每个运动类别的查询结果30分钟。但是,我们无法将此数据传递给用户,因为它需要进一步过滤用户的偏好(例如,他们只想要某些团队/玩家的结果)。对类别和用户首选项执行数据库调用将是令人望而却步的,这就是为什么我们缓存构成所有请求的基础的查询部分(运动类别),但现在想要为用户进一步过滤内存缓存偏好 - 这可以通过Johnny Cache完成,如果是,请问如何?
答案 0 :(得分:5)
简短的回答是肯定的,但是如果不引起其他数据库调用,您将无法使用QuerySet过滤器。您需要遍历返回的结果以避免数据库命中。这取决于您是否要根据返回结果的大小和新筛选查询的查询时间执行此操作。
如QuerySet
文档中所述,a filtered QuerySet returns a new QuerySet that isn't bound by the original。
要进一步了解情况,您可以查看信号johnny.signals.qc_hit
和johnny.signals.qc_miss
以查看何时进行数据库调用。 Signals是一种将回调绑定到某些事件的django机制。在这种情况下,Johnny Cache公开了这两个有用的信号。
我创建了一个简单的应用程序来测试它并帮助演示这种行为。
models.py
from django.db import models
class TestModel(models.Model):
prop_a = models.TextField()
prop_b = models.TextField()
def __unicode__(self):
return "{} {}".format(self.prop_a, self.prop_b)
views.py
from django.dispatch import receiver
from django.http import HttpResponse
from johnny.signals import qc_hit, qc_miss
from models import TestModel
def index(self):
objs = TestModel.objects.all()
print objs
print objs.filter(prop_a='a') #Causes another database or cache hit
return HttpResponse("success")
def generate(self):
generate_data()
return HttpResponse("generated")
def generate_data():
properties = [ 'a', 'b', 'c', 'd', 'e']
for i in xrange(len(properties)):
for j in xrange(len(properties)):
test_model = TestModel(prop_a=properties[i], prop_b=properties[j])
test_model.save()
@receiver(qc_hit)
def cache_hit(sender, **kwargs):
print "cache hit"
@receiver(qc_miss)
def cache_miss(sender, **kwargs):
print "cache miss"
当Johnny Cache通过中间件完成时,您需要通过视图对其进行测试,因为它从请求到响应发生。在上面的例子中,我们有一个非常简单的模型,我们正在查看所有TestModel
个对象,然后是过滤结果。输出将显示每个最初导致高速缓存未命中,然后是高速缓存命中。它们不相关,被视为两个单独的查询。
但是,如果您执行类似
的操作objs = TestModel.objects.all()
result = []
for obj in objs:
if obj.prop_a == 'a':
result.append(obj)
你只会看到一个命中数据库/ johnny缓存。显然,这会得到您想要的结果,但可能会或可能不会慢于另一个查询,具体取决于初始查询的大小。
我希望这有助于回答您的问题并为您提供一种方法来了解缓存如何进一步发挥作用。