2012-09-15 29 views
2

为什么第一个示例抛出TypeError (can't pickle function objects),第二个示例没有,我想这与QuerySet评估(Django 1.4)有关?TypeError不能让pickle函数对象(Django缓存)

def get_or_set_foo_cache(): 
    if not cache.get('foo'): 
     foo = Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1) 
     print type(foo) # prints <class 'django.db.models.query.QuerySet'> 
     cache.set('foo', foo, 60 * 15) 
     return foo 
    return cache.get('foo') 

例2

def get_or_set_foo_cache(): 
    if not cache.get('foo'): 
     foo = Foo.objects.all() 
     print type(foo) # prints <class 'django.db.models.query.QuerySet'> 
     cache.set('foo', foo, 60 * 15) 
     return foo 
    return cache.get('foo') 

如果我设置与列表理解它的工作原理富:

foo = [obj for obj in Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1)] 
+0

你究竟在酸洗什么?当你调用例子2时,你确定'cache'没有'foo'吗? –

+0

哪个版本的Django是它? – jasisz

+0

如果我尝试直接设置缓存,我甚至会得到这个错误。 cache.set('foo',Foo.objects.annotate(bar_count = Count('bar'))。filter(bar_count__gte = 1)) –

回答

5

查询集不是结果对象的列表。当你第一次尝试阅读它的内容时,它是一个延迟评估的对象,它会运行它的查询。但是,当您从控制台打印它时,其输出与对象列表相同。所以大多数人认为他们是简单的名单。

在第二个示例中,您将查询集转换为列表。那就是它的原因。你也可以做

foo = list(Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1)) 

它也可以。

如果稍后您不需要它们作为Foo对象。我建议使用values或values_list操作符。这将带来更快的结果和更小的内存占用。 (http://www.yilmazhuseyin.com/blog/dev/django-orm-performance-tips-part-2/

+0

这就是我从阅读文档中想到的,我尝试将.all()添加到查询哪些似乎没有触发评估 –

相关问题