flask-paginateで検索結果をページネーション


概要

flaskで作成した検索のWEBアプリを、flask-paginateでページネーション(ページ割り)しました。
ページ遷移で少し詰まったので、記事にします。

環境

  • flask 1.1.2
  • flask-paginate 0.7.1

初回作成(不具合あり)

~/resultページから検索条件をPOSTでrequest.formとして取得し、検索した結果がresults(リスト)として得られる状態です。

from flask import Flask, request, redirect, url_for, render_template, flash, session
from flask_paginate import Pagination, get_page_parameter

app = Flask(__name__)

@app.route('/result', methods=['GET', 'POST'])
def show_results():

    # request.formを用いた、なんらかの検索

    results = [...]    # 検索結果(リスト)

    page = request.args.get(get_page_parameter(), type=int, default=1)
    per_page = 1
    res = results[(page-per_page)*per_page: page*per_page]
    pagination = Pagination(page=page, total=len(results), per_page=per_page, css_framework='bootstrap4')

    return render_template('index.html', books=res, request_form=request.form, pagination=pagination)

if __name__ == '__main__':
    app.run(debug=True)

上記コードにより、次のようなページネーションが表示されます。
 

resultsが検索結果の場合、数字の2,3をクリックしてページ遷移すると、正しい結果が表示されません。
検索条件を保存していないので、ページ遷移すると検索条件なしで再検索が行われてしまいます。
(flask-paginateのページ遷移はGETなので、検索条件を取得できません。)

改良(セッションを利用)

検索条件を保存するため、検索の前に以下の処理を入れました。

  1. POSTの場合のみ、request.formをsessionに保存する。
  2. POSTでもGETでも、sessionからrequest.formを割り当てる。session.get('request_form')がなかった場合はNoneが返る。
from flask import Flask, request, redirect, url_for, render_template, flash, session
from flask_paginate import Pagination, get_page_parameter

app = Flask(__name__)
app.secret_key = b'XXXXXXXXX'                     # 追加 sessionを利用するために必要

@app.route('/result', methods=['GET', 'POST'])
def show_results():
    if request.method == 'POST':                  # 追加 
        session['request_form'] = request.form    # 追加 

    request.form = session.get('request_form')    # 追加 

    # request.formを用いた、なんらかの検索

    results = [...]    # 検索結果(リスト)

    page = request.args.get(get_page_parameter(), type=int, default=1)
    per_page = 1
    res = results[(page-per_page)*per_page: page*per_page]
    pagination = Pagination(page=page, total=len(results), per_page=per_page, css_framework='bootstrap4')

    return render_template('index.html', books=res, request_form=request.form, pagination=pagination)

if __name__ == '__main__':
    app.run(debug=True)

これで、ページ遷移すると、sessionに保存された検索条件で検索が行われるので、正しい結果が表示されます。

参考

Flask Paginate(公式)
FlaskのページネーションはFlask-paginateを使うと簡単に実装できる
検索結果のページネーションについて(stack overflow) :Djangoの例