ページ付け—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/2.2.x/topics/pagination
移動先:案内検索

ページ付け

Djangoは、ページ付けされたデータ、つまり「前へ/次へ」リンクを使用して複数のページに分割されたデータの管理に役立ついくつかのクラスを提供します。 これらのクラスはdjango/core/paginator.pyにあります。

Paginator にオブジェクトのリストと、各ページに配置するアイテムの数を指定します。これにより、各ページのアイテムにアクセスするためのメソッドが提供されます。

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2)

>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)
<class 'range_iterator'>
>>> p.page_range
range(1, 3)

>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
['john', 'paul']

>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next()
False
>>> page2.has_previous()
True
>>> page2.has_other_pages()
True
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number()
1
>>> page2.start_index() # The 1-based index of the first item on this page
3
>>> page2.end_index() # The 1-based index of the last item on this page
4

>>> p.page(0)
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3)
Traceback (most recent call last):
...
EmptyPage: That page contains no results

ノート

Paginatorにリスト/タプル、Django QuerySet、またはcount()または__len__()メソッドを使用するその他のオブジェクトを指定できることに注意してください。 渡されたオブジェクトに含まれるオブジェクトの数を決定するとき、Paginatorは最初にcount()の呼び出しを試み、次に渡されたオブジェクトにcount()がない場合は、len()の使用にフォールバックします。 ] 方法。 これにより、DjangoのQuerySetなどのオブジェクトは、使用可能な場合、より効率的なcount()メソッドを使用できます。


ビューでPaginatorを使用する

これは、クエリセットをページ付けするためにビューで Paginator を使用するもう少し複雑な例です。 結果を表示する方法を示すために、ビューと付属のテンプレートの両方を提供します。 この例では、すでにインポートされているContactsモデルがあることを前提としています。

ビュー関数は次のようになります。

from django.core.paginator import Paginator
from django.shortcuts import render

def listing(request):
    contact_list = Contacts.objects.all()
    paginator = Paginator(contact_list, 25) # Show 25 contacts per page

    page = request.GET.get('page')
    contacts = paginator.get_page(page)
    return render(request, 'list.html', {'contacts': contacts})

テンプレートlist.htmlには、オブジェクト自体からの興味深い情報とともに、ページ間のナビゲーションを含める必要があります。

{% for contact in contacts %}
    {# Each "contact" is a Contact model object. #}
    {{ contact.full_name|upper }}<br>
    ...
{% endfor %}

<div class="pagination">
    <span class="step-links">
        {% if contacts.has_previous %}
            <a href="?page=1">&laquo; first</a>
            <a href="?page={{ contacts.previous_page_number }}">previous</a>
        {% endif %}

        <span class="current">
            Page {{ contacts.number }} of {{ contacts.paginator.num_pages }}.
        </span>

        {% if contacts.has_next %}
            <a href="?page={{ contacts.next_page_number }}">next</a>
            <a href="?page={{ contacts.paginator.num_pages }}">last &raquo;</a>
        {% endif %}
    </span>
</div>

Paginatorオブジェクト

Paginator クラスには次のコンストラクターがあります。

class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)

必須の引数

object_list

リスト、タプル、QuerySet、またはcount()または__len__()メソッドを使用するその他のスライス可能なオブジェクト。 一貫したページ付けを行うには、QuerySetを注文する必要があります。 order_by()句を使用するか、モデルのデフォルトの ordering を使用します。

大きなQuerySetをページングするパフォーマンスの問題

非常に多くのアイテムでQuerySetを使用している場合、結果のLIMIT / OFFSETクエリは次のことを行う必要があるため、一部のデータベースでは高いページ番号のリクエストが遅くなる可能性があります。 OFFSETレコードの数を数えます。これは、ページ番号が大きくなるにつれて時間がかかります。

per_page

孤立を含まない、ページに含めるアイテムの最大数(以下のorphansオプションの引数を参照)。


オプションの引数

orphans
アイテムが非常に少ない最後のページを作成したくない場合に使用します。 通常、最後のページにorphans以下のアイテムが含まれている場合、それらのアイテムは、アイテムを単独でページに残すのではなく、前のページ(最後のページになります)に追加されます。 。 たとえば、per_page=10orphans=3の23個のアイテムでは、2つのページがあります。 最初のページには10個のアイテムがあり、2番目(および最後)のページには13個のアイテムがあります。 orphansのデフォルトはゼロです。これは、ページが結合されることはなく、最後のページに1つのアイテムが含まれる可能性があることを意味します。
allow_empty_first_page
最初のページを空にすることができるかどうか。 Falseおよびobject_listが空の場合、EmptyPageエラーが発生します。


メソッド

Paginator.get_page(number)

指定された1ベースのインデックスを持つ Page オブジェクトを返しますが、範囲外および無効なページ番号も処理します。

ページが数字でない場合は、最初のページが返されます。 ページ番号が負の場合、またはページ数より大きい場合は、最後のページが返されます。

Paginator(..., allow_empty_first_page=False)を指定し、object_listが空の場合にのみ、例外( EmptyPage )が発生します。

Paginator.page(number)
指定された1ベースのインデックスを持つ Page オブジェクトを返します。 指定されたページ番号が存在しない場合、 InvalidPage を発生させます。


属性

Paginator.count

すべてのページにわたるオブジェクトの総数。

ノート

object_listに含まれるオブジェクトの数を決定するとき、Paginatorは最初にobject_list.count()を呼び出そうとします。 object_listcount()メソッドがない場合、Paginatorlen(object_list)の使用にフォールバックします。 これにより、DjangoのQuerySetなどのオブジェクトは、使用可能な場合、より効率的なcount()メソッドを使用できます。

Paginator.num_pages
総ページ数。
Paginator.page_range
ページ番号の1ベースの範囲イテレータ。 [1, 2, 3, 4]を生成します。


InvalidPage例外

exception InvalidPage
ページネーターに無効なページ番号が渡されたときに発生する例外の基本クラス。

Paginator.page()メソッドは、要求されたページが無効(つまり、整数ではない)であるか、オブジェクトが含まれていない場合に例外を発生させます。 通常、InvalidPage例外をキャッチするだけで十分ですが、より細かくしたい場合は、次のいずれかの例外をキャッチできます。

exception PageNotAnInteger
page()に整数以外の値が指定された場合に発生します。
exception EmptyPage
page()に有効な値が指定されているが、そのページにオブジェクトが存在しない場合に発生します。

どちらの例外も InvalidPage のサブクラスであるため、単純なexcept InvalidPageで両方を処理できます。


Pageオブジェクト

通常、Pageオブジェクトを手動で作成することはありません。 Paginator.page()を使用して取得します。

class Page(object_list, number, paginator)
len()を使用する場合、または直接反復する場合、ページは Page.object_list のシーケンスのように機能します。

メソッド

Page.has_next()
次のページがある場合はTrueを返します。
Page.has_previous()
前のページがある場合はTrueを返します。
Page.has_other_pages()
次のまたはの前のページがある場合は、Trueを返します。
Page.next_page_number()
次のページ番号を返します。 次のページが存在しない場合、 InvalidPage を発生させます。
Page.previous_page_number()
前のページ番号を返します。 前のページが存在しない場合、 InvalidPage を発生させます。
Page.start_index()
ページネーターのリスト内のすべてのオブジェクトを基準にした、ページ上の最初のオブジェクトの1から始まるインデックスを返します。 たとえば、5つのオブジェクトのリストをページごとに2つのオブジェクトでページ分割する場合、2番目のページの start_index()3を返します。
Page.end_index()
ページネーターのリスト内のすべてのオブジェクトを基準にした、ページの最後のオブジェクトの1から始まるインデックスを返します。 たとえば、5つのオブジェクトのリストをページごとに2つのオブジェクトでページ分割する場合、2番目のページの end_index()4を返します。


属性

Page.object_list
このページのオブジェクトのリスト。
Page.number
このページの1から始まるページ番号。
Page.paginator
関連する Paginator オブジェクト。