matobaの学んだこと

とあるPythonエンジニアのブログ

DjangoのPaginator

DjangoのPaginatorを触ってみる。

Django==1.11 です。

ドキュメントはこちら。

Pagination | Django documentation | Django

import

まず、import

>>> from django.core.paginator import Paginator

django.core にpaginatorパッケージがありその中にクラスがあります。

paginatorの作成

以下のようなオブジェクトがあったとします。

>>> objects = [ f'obj_{x}' for x  in range(7)]
>>> objects
['obj_0', 'obj_1', 'obj_2', 'obj_3', 'obj_4', 'obj_5', 'obj_6']

これを以下のようにして、paginatorに渡してインスタンス化できます。

第二引数は、一つのページに幾つの要素が含まれているかになります。

p = Paginator(objects, 3)

ページ数の確認

以下のようにしてページ数を確認することができます。

>>> p.num_pages
3

ページへのアクセス

paginatorインスタンスに以下のように指定すれば、各ページのインスタンスにアクセスできます。

>>> p.page(1)
<Page 1 of 3>

ページに含まれる要素は以下のようにして確認できます。

>>> p.page(1).object_list
['obj_0', 'obj_1', 'obj_2']

データベースのデータをpaginatorで扱う

データの準備

適当にデータが入っているモデルを作っておきます。

>>> from myapp.models import Blog
>>> Blog.objects.all()
(0.000) SELECT "myapp_blog"."id", "myapp_blog"."title", "myapp_blog"."content" FROM "myapp_blog" LIMIT 21; args=()
<QuerySet [<Blog: Pythonの記事>, <Blog: Rubyの記事>, <Blog: Djangoの記事>, <Blog: 週末のライブ観戦>, <Blog: Pythonの記事2>, <Blog: Pythonの記事3>, <Blog: Pythonの記事1>, <Blog: Pythonの記事4>]>

Paginatorを初期化します。

>>> blogs = Blog.objects.all()
>>> pages = Paginator(blogs , 2)
(0.000) SELECT "myapp_blog"."id", "myapp_blog"."title", "myapp_blog"."content" FROM "myapp_blog" LIMIT 21; args=()

なんで、LIMIT 21のSQLが実行されたんでしょう?

とりあえず、ページ一覧を取得してみます。

>>> pages.num_pages
(0.000) SELECT COUNT(*) AS "__count" FROM "myapp_blog"; args=()
4

ページ一覧を取得する際は、countを実行しているようです。

次は、各ページのオブジェクトを取得します。

>>> pages.page(1).object_list
(0.000) SELECT "myapp_blog"."id", "myapp_blog"."title", "myapp_blog"."content" FROM "myapp_blog" LIMIT 2; args=()
<QuerySet [<Blog: Pythonの記事>, <Blog: Rubyの記事>]>
>>> pages.page(2).object_list
(0.000) SELECT "myapp_blog"."id", "myapp_blog"."title", "myapp_blog"."content" FROM "myapp_blog" LIMIT 2 OFFSET 2; args=()
<QuerySet [<Blog: Djangoの記事>, <Blog: 週末のライブ観戦>]>

各ページのオブジェクトを取得する際は、LIMITとOFFSETを実行しているようです。