# Django 5.0.9.dev20240806133106 ドキュメント

# ページ分割 (Pagination)

Django は、ページ分割 (ページネーション) されたデータを管理するための高レベルと低レベルの方法を提供しています。つまり、"前へ/次へ" リンクを持つ、複数のページに分割されたデータです。

## `Paginator` クラス

内部では、ページ分割に関するすべてのメソッドは `Paginator` クラスを利用しています。このクラスが、実際に `QuerySet` を `Page` オブジェクトに分割する処理をすべて代わりに実行してくれます。

## カスタマイズ例

`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()` メソッドを利用できます。

## `ListView` のページ分割

`django.views.generic.list.ListView` は、表示されたリストをページ分割するビルトインの手段を提供します。そのためには、`paginate_by` 属性をビュークラスに追加します。以下に例を示します。

    from django.views.generic import ListView

    from myapp.models import Contact

    class ContactListView(ListView):
        paginate_by = 2
        model = Contact

これにより、各ページのオブジェクト数が制限され、`paginator` と `page_obj` が `context` に追加されます。ユーザーがページ間を移動できるように、次のようにしてテンプレートに次のページと前のページへのリンクを追加しましょう。

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

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

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

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

## `Paginator` をビュー関数で使用する

以下は、queryset をページ分割するビュー関数内の `Paginator` の一例です。

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

    from myapp.models import Contact

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

        page_number = request.GET.get("page")
        page_obj = paginator.get_page(page_number)
        return render(request, "list.html", {"page_obj": page_obj})

テンプレート `list.html` では、上に示した `ListView` のテンプレートと同じ方法で、ページ間のナビゲーションを追加できます。