【Django】Paginatorクラスの意味・使い方を徹底的に調べてみた。ソースコードを覗いて学んでみた。

Shinです。

Djangoでページネーションを触る機会があったので、良いチャンスだと思って徹底的に調べてみました。

まだクラスやらインスタンスの理解すら覚束ないですが、自分の勉強だと思って1つのクラスに向き合ってみたいと思います。Djangoのページネーションで困ってる人はもしかすると参考になるかも・・・。

【Django】Paginatorクラスを徹底的に調べてみる。

Django公式リファレンスにPaginatorクラスについての詳細があるので、1つずつ紐解いてみました。

後半では分かりやすいように具体例を用いて説明しています。

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

オブジェクトをPaginatorにインスタンス化するときにクラス引数として使えるものが記載されています。

ちょっとDjangoのPaginatorのソースコード覗いてみましょうか。

class Paginator:

    def  __init__(self, object_list, per_page, orphans=0, allow_empty_fitst_page=True):
          self.object_list = object_list
          self._check_object_list_is_ordered() 
          self.per_page = int(per_page)
          self.orphans = int(orphans)
          self.allow_empty_first_page = allow_empty_first_page

第一引数にはobject_listを入れることができます。例えばモデルで定義したデータの全データを変数(object_list)として保持しておき、それをこの第一引数に入れるといった感じです。

第二引数のper_pageは後に具体例で使う,Paginatorクラスの「get_pageメソッド」で使用するint型の数字です。例えばページネーションで6つのデータを1画面に表示して、それ以降は2画面目に表示する・・・といった指示のために使う数字です。

第三引数のorphans=0は初期値として0が代入されています。こちらもget_pageメソッドで使用されているint型の数字ですが、こちらは実際に引数として使用することは、今回の例ではありません。

第四引数のallow_empty_fitst_page=Trueについてですが、最初のページの空を許可するかどうかを判別するbool値です。今回の例では使用しないのでスルーしましょう。

実際に使用するときの具体例を見てみよう

私が実際にPaginatorクラスを使用したときの例がこちら↓

(views.py)

 def publicfunc(request):
    # object_listは全データを取得し、投稿順と逆順で取得。
    object_list = MarioShareModel.objects.all().order_by("-post_date")
    # 逆順で取得したデータを6つまで取得。
    paginator = Paginator(object_list, 6)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    context = {
        'page_obj': page_obj
    }
    return render(request, 'public.html', context)

ちょっと詳しく説明してみます。

object_list = MarioShareModel.objects.all().order_by(“-post_date”)

こちらはクエリセットですね。

各自用意したモデルの全データをobject_list変数の中に格納しています。.order_by(“-post_date”)は投稿順にクエリを抽出したかったので書いてます。

これは各々とってきたいクエリを指定してください。

paginator = paginator(object_list, 6)

今回の本題の1行です。

paginatorクラスをインスタンス化しています。第一引数には先ほど作ったobject_list(モデルで定義した中での全データを取得しているクエリセット)。第二引数にはper_pageで設定する「6」というint型の数字をとっています。

この6という数字は各々決めてもらって構いません。私は1画面内に6つまで表示したかったので6としています。これが10でも20でも構いません。

これでpaginatorというインスタンスが出来上がりました。これでpaginatorクラス内にある属性、メソッドが自由に使えるようになっています。

page_number = request.GET.get(‘page’)

続いてrequest.GET.get()です。

これはHTTPReqeustにクラスついての知識が必要になります。

そもそもrequestとは、クライアント側がサーバーにリクエストを投げたときのクライアント情報が格納されています(methodやurl,user情報などたくさん入っています)。

request.GETとすることでそれらのデータを辞書ライクな(正確にはQueryDict型)で取得することができます。辞書型で取得できることによって、get()というpython文法でその中身を取得することができるわけですね。

引数にはget(’page’)ということで、QueryDictに入っている’page’というキーから値をとってくることができます。キーがそもそもなければNoneが返ります。値が入ってないだけならデフォルト値を返すようです。

page_obj = paginator.get_page(page_number)

先ほど作ったpaginatorインスタンスを使っていきます。

paginatorクラスが持っているget_pageというメソッドが何なのかを覗いてみましょう。


def get_page(self, number):
        """
        Return a valid page, even if the page argument isn't a number or isn't
        in range.
        """
        try:
            number = self.validate_number(number)
        except PageNotAnInteger:
            number = 1
        except EmptyPage:
            number = self.num_pages
        return self.page(number)

返り値は「引数が数字または範囲指定でなくても、有効なページを返す」と書いてますね。

とりあえずnumberという変数にself.vaildate_number(number)を入れます。try except文なので、有効な数字を探しているようです。

ちょっと文章量が多くなりそうなので、ここで一旦終わりにします。すみません。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です