web-dev-qa-db-ja.com

Django querysetでのiterator()の使用

最近、奇妙な行動に出くわしたので、理解度を確認する必要があります。

モデルで単純なフィルターを使用して、結果を反復処理しています。

例えば.

_allbooks = Book.objects.filter(author='A.A. Milne')

for book in allbooks:
   do_something(book)
_

奇妙なことに、それは本の部分的なリストだけを返していました。

ただし、同じコードを使用してiterator()を使用する場合、これはうまく機能するようです。

つまり.

_for book in allbooks.iterator():
    do_something(book)
_

理由は何ですか?

p.s. Djangoのドキュメントを調べましたが、クエリセットが他の場所にすでにキャッシュされている方法がわかりません...

iterator()(クエリを実行して)QuerySetを評価し、結果に対してイテレータを返します。 QuerySetは通常、結果を内部にキャッシュして、評価を繰り返しても追加のクエリが発生しないようにします。 iterator()は、代わりに、QuerySetレベルでキャッシュを実行せずに、結果を直接読み取ります。多数のオブジェクトを返すQuerySetの場合、これによりパフォーマンスが向上し、メモリが大幅に削減されることがよくあります。

すでに評価されているQuerySetでiterator()を使用すると、クエリが繰り返されて、再度評価されることに注意してください。

16
gingerlime

奇妙なことに、それは本の部分的なリストだけを返していました。

これは、クエリセットが機能する必要がある方法ではありません。クエリセットを反復処理すると、データベースから返されるすべてのレコードが得られます。コードをデバッグします。エラーが見つかります。それ以外の場合は、再度デバッグしてください。

REPLでチェックインするのは簡単です。実行manage.py Shell

from app.models import Model
for o in Model.objects.filter(fieldname="foo"): print o

#Let's see DB query
from Django.db import connection
print(connection.queries)
21
alex vasi

QuerySetは通常、結果を内部にキャッシュして、評価を繰り返しても追加のクエリが発生しないようにします。対照的に、iterator()は、QuerySetレベルでキャッシュを実行せずに、結果を直接読み取ります。

https://docs.djangoproject.com/en/dev/ref/models/querysets/

1