Django ページネーション(django-pure-pagination)を実装する

シェアする

リストページを作成するとき、1ページに表示する数を20件にして、残りは2ページ目、3ページ目・・・みたいなことをします。これをページネーションといいます。

Django は元々ページネーションの仕組みがあり便利ですが、ページネーション用のパッケージを使うと、さらに便利になります。

私は昔からよく django-pagination を使うのですが、今は他にも良さそうなのが、たくさんあるみたいです。

そこで今回は、いつも使い慣れている django-pagination ではなく、Github で Star がたくさんついている、django-pure-pagination を使ってみたいと思います。

完成イメージ

バージョン

  • Python 3.6.4
  • Django 2.0.3
  • django-pure-pagination 0.3.0

インストール

Python, Django のインストール

Python と Django のインストールについては、こちらの記事を参考にしてください。

django-pure-pagination のインストール

$ sudo pip install django-pure-pagination
Collecting django-pure-pagination
 Downloading https://files.pythonhosted.org/packages/55/43/50c475f408d3350cec340855970a5ce02ea12f5a53d520315f200b4847a1/django-pure-pagination-0.3.0.tar.gz
Installing collected packages: django-pure-pagination
 Running setup.py install for django-pure-pagination ... done
Successfully installed django-pure-pagination-0.3.0

django-pure-pagination の使い方

django-pure-pagination の Github にサンプルプログラムがありますので、それを参考にしたいと思います。

settings.py

ALLOWED_HOSTS = ['*']
INSTALLED_APPS = (
    ...
    'pure_pagination',
    'core'
)
TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        ...
    }
]

settings.py は startproject で生成し、差分だけを載せています。startproject がわからない場合は、こちらの記事を参考にしてください。

INSTALLED_APPS に先ほどインストールした ‘pure_pagination’ と ページネーションを使う APP ‘core’ を追加します。

外部からのアクセスを許可するために、ALLOWED_HOSTS に ‘*’ を追加しています。

ページネーション結果を表示するテンプレート置き場を、TEMPLETES の DIRS に設定しています。

urls.py

from django.urls import path
from core.views import index

url patterns = [
    path('', index, name='index'),
]

names.py

names.py

ページネーションするには、それなりに大量のデータが必要です。DB に自分でテストデータを作っても良いのですが、django-pure-pagination のサンプルプログラムに、5,607 件のアルファベット順のデータがありますので、それを使います。

views.py

from random import randint

from django.http import Http404
from django.shortcuts import render_to_response

from pure_pagination.paginator import Paginator

from core.names import names

def index(request):
    how_many_names = request.GET.get('how_many_names', 60)
    page_size = request.GET.get('page_size', 10)
    page_num = request.GET.get('page', 1)
    try:
        page_num = int(page_num)
        page_size = int(page_size)
        how_many_names = int(how_many_names)
    except ValueError:
        raise Http404

    selected_names = []
    total = len(names)
    for i in range(how_many_names):
        selected_names.append(names[randint(0, total - 1)])
    p = Paginator(selected_names, page_size, request=request)

    page = p.page(page_num)
    return render_to_response('index.html', {
        'page': page,
    })

views.py はサンプルプログラムから拝借しています。

GET パラメータがあれば、その条件で絞り込んでいます。なければ、デフォルトの設定で動きます。

その後、ランダムでページネーション対象データを表示します。

index.html

<!DOCTYPE html>
<html>
<head>
    <title>Test page</title>

    <style type="text/css">
        body{
            font-family: Arial;
            font-size: 12px;
        }
        .name-box{
            padding: 10px;
            font-size: 12px;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
        .spacer{
            clear:both;
            height: 10px;
        }
        .page, .prev, .next{
            display: inline-block;
            padding: 3px 5px;
            border: 1px solid #ddd;
            border-radius: 5px;
            text-decoration: none;
            color: #333;
            background: #eee;
            font-weight: bold;
        }
        .page:hover, .prev:hover, .next:hover{
            background: #333;
        }
        .page.current{
            background: #333;
            color: white;
        }
        .page.disabled, .prev.disabled, .next.disabled{
            color: #ddd;
            cursor: default;
        }
        form{
            padding: 10px 5px;
            border: 1px solid #ddd;
        }
        form div{
            padding: 5px;
        }
        form label{
            width: 133px;
            display: inline-block;
        }
        form input[type="submit"]{
            font-size: 12px;
            cursor: pointer;
        }
    </style>

</head>
<body>
    <form action="" method="GET">

    <div>
        <label for="how_many_names">How many names?</label>
        <input type="text" name="how_many_names" value="60">
    </div>

    <div>
        <label for="how_many_names">Items per page?</label>
        <input type="text" name="page_size" value="10">
    </div>

    <input type="submit">

    </form><div class="spacer"></div>

{% for name in page.object_list %}

    <div class="name-box">

    Name: {{ name }}

    </div><div class="spacer"></div>

{% endfor %}

{{ page.render }}

</body>
</html>

ページネーションを表示するテンプレートです。

tree

$ tree
.
├── core
│   ├── __init__.py
│   ├── apps.py
│   ├── names.py
│   └── views.py
├── manage.py
├── pagination
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── templates
    └── index.html

3 directories, 10 files

ファイル構成はこのようになりました。

実行

$ python3.6 manage.py runserver 0.0.0.0:8000

runserver を実行して、ブラウザから http://IPアドレス:8000 にアクセスし、ページネーションの動きが確認できると思います。

まとめ

今回、初めて django-pure-pagination 使ったのですが、なかなか使いやすくて良かったです。

しかし、普段使っている django-pagination は、テンプレートだけで実装できて、かなり強力です。

使いやすさを比べると、django-pagination に軍配があがる気がします。(django-pure-pagination のテンプレートだけ実装方法を私が知らないだけかもしれません。)

もしかしたら、使い込んでいくうちに、django-pagination より django-pure-pagination の方が、良く感じるかもしれないので、もう少し使ってみたいと思います。

Django のページネーションパッケージは、他にもたくさんありますので、自分にあったベストなページネーションを今後も探求していきたいと思います。