ページネーション
1ページでは表示できないほどのデータがあるとき、これらを複数のページに分割して表示する機能のことをページネーション、またはページングと呼び、Webアプリケーションでよく提供される機能の1つです。
TreeFrog Framework では、ごく基本的な機能をもつページネーションクラスを用意しています。TPaginator というクラスを使って、実装していきます。以下の例は ERB で記述しますが、Otama でも同様なものになります。
まず、アクションの中で、表示するページ番号をクエリ引数を使って受け取ります。その番号に該当するモデルのリストを取得し、ビューへ渡します。
int current = httpRequest().queryItemValue("page", "1").toInt();
int totalCount = Blog::count();
// 1ページに最大10件の項目を表示。ページ番号は5個表示。
TPaginator pager(totalCount, 10, 5);
pager.setCurrentPage(current); // 現在のページを設定
texport(pager);
// 該当する項目を取得し、ビューへ受け渡し
QList<Blog> blogList = Blog::getBlogs( pager.itemCountPerPage(), pager.offset() );
texport(blogList);
render();
次はビューです。
ページ番号を表示するには、部分テンプレートを使用するのが良いでしょう。
次の例では、渡された TPaginator オブジェクトを使って、ページ番号とそのリンクを描画しています。urlq()メソッドは、現在のアクションに対して、指定したクエリ引数を追加したURLを生成します。
テンプレート: views/partial/pagination.erb
<%#include <TPaginator> %>
<% tfetch(TPaginator, pager); %>
<div class="pagination">
<%== linkToIf(pager.hasPrevious(), "Prev", urlq("page=" + QString::number( pager.previousPage() ))) %>
<% for (QListIterator<int> i(pager.range()); i.hasNext(); ) {
int page = i.next(); %>
<%== linkToIf((page != pager.currentPage()), QString::number(page), urlq("page=" + QString::number(page))); %>
<% } %>
<%== linkToIf(pager.hasNext(), "Next", urlq("page=" + QString::number( pager.nextPage() ))) %>
</div>
部分テンプレートを描画する方法は、次のとおりでした。
<%== renderPartial("pagination") %>
また、このテンプレートでは、コントローラから渡されたモデルの一覧を描画します。繰り返しになるのでコードは省略します。ジェネレータで作成した index テンプレートなどを参考にしてださい。
次に、モデルの取得です。
該当するモデルの一覧を取得するには、データベースに対して、LIMIT 句 と OFFSET 句を指定したクエリを発行すれば良いでしょう。要件によっては、WHERE句やソートを指定する必要があるかもしれませんね。
このような SQL クエリはよく使われることから、次のTreeFrog Framework のユーティリティ関数を使うと短いコードで済みます。
QList<Blog> Blog::getBlogs(int limit, int offset)
{
return tfGetModelListByCriteria<Blog, BlogObject>(TCriteria(), limit, offset);
}
追記:
ちなみにですが、ページネーションはそれほど難しい機能ではないので、TPaginator を使わなくとも独自に実装できると思います。これで足りなければ、実装にチャレンジしてみてください。