Life is Really Short, Have Your Life!!

ござ先輩の主に技術的なメモ

FlaskでPaginationを実現する方法(Flask-SQLAlchemyを使用)

いやー、Flaskはドキュメントが断片的だ。マイクロフレームワークだとドキュメントもマイクロなんでしょうか。順番に追っていきます。

View部分のコードはこんな感じです。

from flask.ext.sqlalchemy import Pagination

@app.route('/user', defaults={'page': 1})
@app.route('/user/<int:page>')
def user_index(page):
    per_page = 20

    name = request.args.get('name', '')
    p = User.query.filter((User.name.like('%' + name + '%')) | (not name)).\
        order_by(User.username.asc()).paginate(page,perpage)

    return render_template( 'user.html', pagination=p,name=name)
Paginationを作成する

Flask-SQLAlchemyを使っている前提ですが、Flask-SQLAlchemyにはPagination作成用のクラスが用意されており、SQLAlchemyのqueryオブジェクトに対してpaginateメソッドを呼ぶだけです。簡単。

https://pythonhosted.org/Flask-SQLAlchemy/api.html#utilities

検索条件をrender_templateで渡しているのは検索条件付きのpaginationを生成するためにセットしています。

また、検索結果はpaginationオブジェクトのitemプロパティに格納されます。上記の例で言うと{{ for v in pagination.items}}でループできます。

pagination用のテンプレートを作る

Simple Pagination | Flask (A Python Microframework)では、Flask-SQLAlchemyが作られる前の話のようで、自分で簡単なPagingComponentを作っています。でも、Flask-SQLAlchemyを利用していれば必要ありません。

また、あのスニペットでは検索条件の引き渡しが全く考慮されておりません。ヘルパーをjinja2に登録しないと動かないってのも、なんか好みじゃない。テンプレート側でページ送り用のviewの関数と検索条件を渡すだけで良い話だし。

色々探した結果、この前買った書籍「Flask Web Development」にナイスなjinja2マクロが定義されていました。下記をそのまま活用しちゃいました。

flasky/_macros.html at master · miguelgrinberg/flasky · GitHub

テンプレートでページ送りを書く
{% import "_pagination.html" as p %}
{% if pagination %}
{{ p.pagination_widget(pagination,'.user_index',name=name) }}
{% endif %}

ちょーシンプルでしょ。さっきのマクロを呼び出す。見ての通り、第1引数はpaginationのオブジェクト、第2引数はurl_forで呼び出すviewの関数。第3引数に引き継ぎたい検索条件を渡すだけです!

参考書籍

Flask Web Development: Developing Web Applications with Python

Flask Web Development: Developing Web Applications with Python

この著者の人はThe Flask Mega-Tutorial, Part I: Hello, World! - miguelgrinberg.comってのを書いている人で、それをまとめて加筆した本が上記です。英語がとても平易なので、オススメしておきます。