3

最初の例がスローTypeError (can't pickle function objects)され、2番目の例がスローされないのはなぜですか?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)]
4

1 に答える 1

6

クエリセットは結果オブジェクトのリストではありません。これは、コンテンツを最初に読み取ろうとしたときにクエリを実行する、遅延評価されたオブジェクトです。ただし、コンソールから印刷すると、出力はオブジェクトのリストと同じになります。そのため、ほとんどの人はそれらを単純なリストと考えています。

2 番目の例では、クエリセットをリストに変換しています。それが機能する理由です。あなたもできる

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

于 2012-09-18T10:36:10.347 に答える