Django/Python sorting after getting cached results
Greetings,
A few quick things (django 1.2.3, python 2.6, memcached).
I have a function where I first do a somewhat expensive query, when I do this quer开发者_运维问答y I do an oder_by. I then update some values which may change the order of the results. I then put all of the values in the cache.
Then in another function I get the cache and I want to resort the results so that they are again in order.
so this would be something like.
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 )
based on other posts I would think this should work but I get a typeerror saying that my_cache_list is unsubsriptable.
Anyone have any ideas? Im probably doing something stupid....
thanks.
NOTE: Update made change operator.attrgetter for operator.itemgetter removed error! This code above does work. The problem was in using the operator.itemgetter.
The Python function sorted()
works with Mutable List Types, which a Django queryset is not: this is what the error you're getting is basically telling you. Technically, subscripting is the act of accessing a list element by its index, like this:
list = ['a', 'b', 'c']
list[0] # This is a subscript
If you try that on a queryset, it will fail with the same exception you got:
list = MyModel.objects.all()
list[0] # This subscript will fail: a queryset doesn't support the operation
If you want to keep your scheme of loading an ordered queryset, caching the results and reordering them on cache access, you will have to turn your queryset into a real list and store that in cache (this will take a lot more cache space, though). In your function 1:
qs = myevent.people.order_by('-score')
mylist = list(qs.all())
....do up date....
cache.set(cache_key, mylist)
There is one thing that jumps out from your example code. You seem to be treating your cache as a reliable datastore. You should never assume that the cache will return a value.
my_cache_list
is probably None
when you're getting the TypeError
, which means that the cache key was not found. You should always test for a None
value and regenerate the value.
As you're using the memcache backened you need to remember that you can only store values up to 1MB in size. Values larger than this are silently discarded.
try to pickle your list before you set it in cache:
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 )
精彩评论