web-dev-qa-db-ja.com

Django怠惰なQuerySetとページネーション

here that Djangoクエリセットは怠惰で、実際に印刷されるまで評価されません。Djangoの組み込みのページ付けを使用して簡単なページ付けを行いました。 。「Django-pagination」や「Django-endless」など、その仕事をするアプリがすでにあることに気づきませんでした。

とにかく、たとえばこれを行うときに、QuerySetがまだ怠惰であるかどうか疑問に思います

entries = Entry.objects.filter(...)
paginator = Paginator(entries, 10)
output = paginator.page(page)
return HttpResponse(output)

そして、この部分は、現在表示したいページを取得するたびに呼び出されます。

データベースに不必要な負荷をかけたくないので、知る必要があります。

21
starcorn

どこで発生しているかを確認したい場合は、import Django.db.connectionそしてqueriesを検査します

>>> from Django.db import connection
>>> from Django.core.paginator import Paginator
>>> queryset = Entry.objects.all()

ページネーターを作成して、クエリが発生するかどうかを確認しましょう。

>>> paginator = Paginator(queryset, 10)
>>> print connection.queries 
[]

まだありません。

>>> page = paginator.page(4)
>>> page
<Page 4 of 788>
>>> print connection.queries 
[{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}]

ページを作成すると、クエリセットに含まれるエントリの数をカウントする1つのクエリが生成されます。エントリはまだフェッチされていません。

ページのオブジェクトを変数 'objects'に割り当てます。

>>> objects = page.object_list
>>> print connection.queries
[{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}]

これはまだエントリがフェッチされる原因にはなりません。

オブジェクトリストからHttpResponseを生成します

>>> response = HttpResponse(page.object_list)
>>> print connection.queries
[{'time': '0.014', 'sql': 'SELECT COUNT(*) FROM `entry`'}, {'time': '0.011', 'sql': 'SELECT `entry`.`id`, <snip> FROM `entry` LIMIT 10 OFFSET 30'}]

最後に、エントリがフェッチされました。

44
Alasdair

です。 Djangoのページ付けでは、クエリセットに適用されるのと同じルール/最適化が使用されます。

これは、return HttpResponse(output)で評価を開始することを意味します

3
rantanplan