【问题标题】:TypeError can't pickle function objects (Django caching)TypeError 不能腌制函数对象(Django 缓存)
【发布时间】:2012-09-08 09:37:35
【问题描述】:

为什么第一个示例抛出TypeError (can't pickle function objects) 而第二个没有,我想这与 QuerySet 评估(Django 1.4)有关?

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 设置为列表理解,它会起作用:

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

【问题讨论】:

  • 你到底在腌什么?当您调用示例 2 时,您确定 cache 没有 foo 吗?
  • 那是哪个版本的 Django?
  • 如果我尝试直接设置缓存,我什至会收到此错误,例如cache.set('foo', Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1))

标签: python django caching django-orm django-cache


【解决方案1】:

Queryset 不是结果对象的列表。它是一个惰性求值的对象,当您第一次尝试读取其内容时会运行其查询。但是当您从控制台打印它时,它的输出与对象列表相同。所以大多数人认为它们是简单的列表。

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

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/)

【讨论】:

  • 这就是我阅读文档时的想法,我尝试将 .all() 添加到似乎没有触发评估的查询中
猜你喜欢
  • 2022-07-16
  • 2020-06-26
  • 2016-03-27
  • 2017-10-23
  • 2019-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多