Django/Python 获取缓存结果后的排序
你好,
有一些简单的事情想说(使用的是django 1.2.3,python 2.6,还有memcached)。
我有一个函数,首先会进行一个比较耗时的查询。在这个查询中,我会使用一个排序功能(order_by)。接着,我会更新一些值,这可能会改变结果的顺序。最后,我把所有的值放进缓存里。
然后在另一个函数中,我获取缓存的数据,想要重新排序这些结果,让它们再次按顺序排列。
大概是这样的。
function 1():
mylist = myevent.people.order_by('-score')
....do up date....
cache.set(cache_key,mylist)
function(2):
my_cache_list = cache.get(cache_key)
newlist = sorted(my_cache_list,key=operator.attrgetter('score'), reverse=True )
根据其他人的帖子,我觉得这样应该可以正常工作,但我遇到了一个类型错误,提示说我的缓存列表(my_cache_list)不能被订阅(unsubscriptable)。
有没有人有什么想法?我可能做了什么傻事……
谢谢。
注意:更新后,使用了operator.attrgetter替代operator.itemgetter,解决了错误!上面的代码现在可以正常工作。问题出在使用operator.itemgetter上。
3 个回答
在你把列表放进缓存之前,试着先把它“腌制”一下:
import cPickle as pickle
cache.set(pickle.dumps(mylist))
function(2):
my_cache_list = cache.get(cache_key)
newlist = sorted(pickle.loads(my_cache_list),key=operator.itemgetter('score'), reverse=True )
从你的示例代码中,有一点很明显。你似乎把缓存当成了一个可靠的数据存储。其实你永远不能指望缓存一定会返回一个值。
当你遇到TypeError
时,my_cache_list
很可能是None
,这意味着找不到对应的缓存键。你应该总是检查一下是否是None
,如果是的话就重新生成这个值。
因为你在使用memcache这个后端,所以要记住,你只能存储最大为1MB的值。超过这个大小的值会被默默丢弃。
Python中的 sorted()
函数是用来处理可变列表的,而Django的查询集(queryset)并不是可变的。这就是你遇到的错误的意思。简单来说,"下标访问"就是通过索引来获取列表中的某个元素,比如这样:
list = ['a', 'b', 'c']
list[0] # This is a subscript
如果你在查询集上这样做,就会出现和你之前一样的错误:
list = MyModel.objects.all()
list[0] # This subscript will fail: a queryset doesn't support the operation
如果你想保持加载有序查询集的方式,缓存结果并在访问缓存时重新排序,你需要把查询集转换成一个真正的列表,并把它存储在缓存中(不过这样会占用更多的缓存空间)。在你的函数1中:
qs = myevent.people.order_by('-score')
mylist = list(qs.all())
....do up date....
cache.set(cache_key, mylist)