[Django] Paginatorに渡すobject_listを自作クラスでラップ
2008年12月25日
Django-1.0から出来たPaginatorですが、
インスタンス生成時にページングしたい全要素のリストを渡さないといけない点が、若干不便。
インスタンス生成時にページングしたい全要素のリストを渡さないといけない点が、若干不便。
というのも、object_listにQuerySetインスタンスを渡すならば、
遅延評価して抽出された各要素のみを生成するからいいんですが、
渡すリストにそのような遅延評価の機能が無い場合は、
「全要素を生成して渡し、その中で表示するページ分だけの要素を使う。」
という、非効率なことになってしまう。
リストが無視できるデータ量ならいいんだけど、
自分の場合に無視できない問題になってしまったので、
以下のようにして対応しました。
(1) こういうクラスを作って・・・
class SomeObjectList(object): def __getitem__(self, key): start = None stop = None if isinstance(key, int): start = key stop = key + 1 elif isinstance(key, slice): start = key.start stop = key.stop else: raise IndexError if 0 > start: raise IndexError items = [] # ある行数が多いデータから、上記の start / end を使用して # 一部だけ抽出してitemsへ格納して返す。 return items def count(self) count = 0 # ある行数の多いデータから、全体の個数を素早く取得できる手段で取得して返す。 # 例えば、SQLのCOUNT文的に。 return count
(2) ・・・こんな風にPaginatorを生成させる
Paginator(SomeObjectList(), 10)
とりあえず、object_listだよって、「枠」だけ渡して、
中身は paginator.page とかで、実際に評価された時に生成させるという感じです。
このPaginatorの仕様なんですけど、
(a) Paginatorインスタンス生成時には、全体の個数だけ渡して。
(b) paginator.page に対して、対応するobject_listを設定する。
(c) QuerySetとの連携は、ObjectPaginatorサブクラスで対応する。
・・・という方が、より疎結合でDjangoのイメージに合っている気がするんだけどなー。
(a) Paginatorインスタンス生成時には、全体の個数だけ渡して。
(b) paginator.page に対して、対応するobject_listを設定する。
(c) QuerySetとの連携は、ObjectPaginatorサブクラスで対応する。
・・・という方が、より疎結合でDjangoのイメージに合っている気がするんだけどなー。
まぁ、上記のような抜け道を用意してくれているので、これでやってね、ってことか。
と、何かおかしかったらご指摘願います!!