Plone で Batch を使って○件毎にページ分割する

Plone で検索結果や News の記事とかを30件ずつ表示したいって感じのときに便利な Batch ってクラスがあったのでメモ。
~/Plone-3.0.6/zinstance/Products/CMFPlone/PloneBatch.py ってとこにある。

基本的な使い方

ページテンプレート上での使い方は ZMI から portal_skins/plone_forms/search を見てもらうとなんとなくわかる。例えば Plone サイト上の News を10件ずつ表示させるページでも作るとするとこんな感じ。

<div tal:define="results python:context.portal_catalog.searchResults(Type='News');
                      Batch python:modules['Products.CMFPlone'].Batch;
                      b_start python:0;b_start request/b_start|b_start;">
<tal:results define="batch python:Batch(results, 10, int(b_start));">
<tal:block repeat="result batch">
    <p>
        <a href="#" tal:content="result/Title" 
                        tal:attributes="href result/getURL" />
    </p>
</tal:block>
    <div metal:use-macro="here/batch_macros/macros/navigation" />
</tal:results>
</div>

この部分でページナビゲーションのテンプレートを呼び出していて

<div metal:use-macro="here/batch_macros/macros/navigation" />

こんな感じで表示される。(おそらくデフォルト)

<< Previous 10 items     Next 10 items >>      2  3  4 [5]  6  7  8

もしもこのナビゲーション部分のデザインが気に入らんようなら portal_skins/plone_templates/batch_macros をカスタマイズするなり、参考にして新たなマクロを定義するなりすればいいと思う。

色んなオプションがあるらしい

Batch に渡せる引数は全部で9個。で、基本的に必須なのは上の3つ。あとのやつでカスタマイズ。

sequence
分割して表示させたいオブジェクトのリスト。上の例でいう searchResults とかで取得したリスト。(必須)
size
1ページあたりの表示件数。(必須)
start
1番最初にページに表示するオブジェクトのインデックス。ここは int(b_start) とかやって動的に取得しとかないとちゃんとナビゲーションが動いてくれない。(とりあえず必須)
end
ページで最後に表示するオブジェクトのインデックス。普通、指定することはないと思う。
orphan
残りのオブジェクトがこの数字以下に収まるなら前のページと統合して表示する。なので、最後のページの表示件数は size+orphan になるはず。デフォルトは0。
overlap
各ページで前のページから被らせて表示させる件数。例えば、overlap=2, size=5 って指定した場合 [1, 2, 3, ..., 20] ってリストがあったら、[1, 2, 3, 4, 5] → [4, 5, 6, 7, 8] → [7, 8, 9, 10, 11] って感じでページ分割されていく。デフォルトは0。
pagerange
ナビゲーション部分に表示されるページ番号リンクの数。デフォルトは7。
quantumleap
ページ数が多いとき、通常のナビゲーションに表示されるページ番号リンクに便利なショートカットを増やす。値は0か1(1で有効)を指定する。デフォルトは0。例えばページ数が100あって現在表示中のページが50の場合、こんな感じで表示される。はず。
<< Previous 10 items     Next 10 items >>      17  32  46  47  49  [50]  51  52  53  68  83

ページテンプレート上で表示させるには leapback, leapforward って関数を使う。カスタマイズするときに間違って消してしまわないよう注意。

b_start_str
各ページへのリンクURLから start の値を得るためのクエリ変数名。デフォルトでは b_start になっている。なんか違和感があるなら page とか指定してみると自然かも。

-C ってクエリが勝手にくっついてくる問題

上の方法のようにページテンプレート内で searchResults とかして表示させようとすると、次ページのリンクURLに「?b_start=int:10&-C=」って感じで身に覚えのない -C って輩が出てきたりすることがある。このページによると、どうやらバグらしいんだけどなんか気持ち悪い。
なので、無理矢理だけど、 portal_skins/plone_templates/batch_macros から request.form を消して直してみた。
この方法だと、リクエストで投げた他のクエリも全部受け取ってくれなくなっちゃうけど、そもそも他のクエリを投げた場合にはこの「-C が勝手についてくる問題」は発生しないので大丈夫。だと思う。


いやー Django とかにはちゃんと pagination ってあるのになんで Plone にはないんだろうってずっと思ってたけど、探してみたら普通に使われてたっていう。今までこいつの存在を知らんかったので、ページテンプレートとスクリプトで無理矢理ページ分割&ナビゲーションを実装しちゃったりしてた。まじで無駄だ。。
一応簡単な説明は以下にありました。
Using Plone's built-in batching mechanism — Plone CMS: Open Source Content Management