TypeError can't pickle function objects (Django caching)
-
02-07-2021 - |
Вопрос
Why does the first example throw TypeError (can't pickle function objects)
and the second one doesn't, I suppose it's got to do with QuerySet evaluation (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')
Example 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')
If I set foo with list comprehension it works:
foo = [obj for obj in Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1)]
Решение
Queryset is not a list of result objects. It is a lazily evaluated objects that runs its query when you first try to read its content. But when you print it from the console its output is same as list of objects. So most people think them as simple lists.
At the second example you are converting your queryset to a list. Thats why it works. You could also do
foo = list(Foo.objects.annotate(bar_count=Count('bar')).filter(bar_count__gte=1))
And it would work too.
If you won't need them as Foo objects later on. I suggest to use values or values_list operator. Which will give faster results and smaller memory footprint. ( http://www.yilmazhuseyin.com/blog/dev/django-orm-performance-tips-part-2/ )