[Flask]Flashメッセージを実装する
はじめに
PythonのWebアプリケーションフレームワークFlaskを使って、「消耗品買い物リスト」を作ってみるシリーズ第13回目です。
今回は、操作をした場合に何が起きたかユーザーにわかりやすく伝えるFlashメッセージを実装します。
前回まで
- 0回 : Flaskで簡単なWebサービスを作ってみる
- 1回 : スプレッドシート+Google Apps Scriptでプロトタイプを作る
- 2回 : FigmaでUI制作をしてみたが早々に次のフェーズに進んだ件
- 3回 : DockerでFlaskが動き、簡単なテストが通る状態を作る
- 4回 : [スクショ付き]AWSにVPCを構築し、EC2を立てる
- 5回 : EC2でDockerコンテナを起動し、Flaskを動かす
- 6回 : CircleCIでFlaskアプリの自動テストができるようにする
- 7回 : CircleCIでIP制限のあるEC2インスタンスに自動デプロイできるようにする
- 8回 : ユーザーストーリーマッピングで初期開発機能を洗い出す
- 9回 : [Flask]uuidを生成して専用URLを作成する
- 10回 : flask-sqlalchemy/flask-migrate/mysql-connector-pythonでMySQL連携を実装する
- 11回 : [Flask-SQLAlchemy]レコードの登録機能の実装
- 12回 : [Flask-SQLAlchemy]レコード編集と論理削除による削除機能の実装
- 13回 : [Flask-SQLAlchemy]レコード更新ログを実装する/autoincrementの値をレコード挿入時に取得する方法
Flashメッセージとは?
ユーザーが操作をしたときに、画面にその結果を表示する機能やメッセージのことです。
例えば、ログインした時に「ログインしました」と出したり、新規投稿をした時に「投稿しました」と表示するものです。
投稿に失敗した時には「投稿に失敗しました」と出すことで、ユーザーは自分の操作の成功/失敗がすぐに分かります。
サービスの使い勝手を高める上で必須の要素です。
SECRET KEYの追加
FlaskでFlash機能を使うには、secret_keyを設定する必要があります。
config.pyのDevelopmentConfigクラスにSECRET_KEY変数を追加します。
値は何でも良いですが、os.urandom(24)で生成された値が推奨されています。
- config.py
import os
class DevelopmentConfig:
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'mysql+mysqlconnector://{user}:{password}@{host}/{database}?charset=utf8mb4'.format(
**{
'user': os.getenv('DB_USER', 'XXX'),
'password': os.getenv('DB_PASSWORD', 'XXX'),
'host': os.getenv('DB_HOST', 'XXX'),
'database': os.getenv('DB_DATABASE', 'app')
}
)
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = False
# os.urandom(24)で生成
SECRET_KEY = b'g\xebQ\xe9\x1a\xa7\x05z\xb6\xc3\xab\xd8Y\xcc\xd21\xda\xc2\t\\\xd4\xbd0\xf0'
Config = DevelopmentConfig
なお、SECRET_KEYなのでソースコードに直接書くのはリスクがあります。
今は開発用なので良いですが、本番環境に展開する前には、この値をどこに置いておくか検討して対応しておくのを忘れないようにしましょう。
公式ドキュメントで設定について細かく説明されているので、どこかのタイミングでしっかり読み込んでおきたいと思います。
Flashの追加
ページの作成/アイテムの作成/変更/削除でそれぞれ、flash(‘Message’)を実行し、Viewを返すようにします。
追加した箇所以外は割愛しています。
- app.py
from flask import Flask, render_template, request, redirect, url_for, flash # flashを追加
...
@app.route('/page/create')
def create_new_page():
"""新規ページを作成する
"""
...
try:
db.session.add(user_page)
db.session.commit()
flash('A new page has been created!')
return redirect(url_for('show_user_page', uuid=uuid))
...
@app.route('/page/create')
def create_new_page():
"""新規ページを作成する
"""
...
try:
db.session.add(user_page)
db.session.commit()
flash('A new page has been created!')
return redirect(url_for('show_user_page', uuid=uuid))
...
@app.route('/page/<uuid>/item/create', methods=['POST'])
def create_new_item(uuid):
"""新規アイテムを作成する
"""
...
try:
db.session.add(item)
db.session.flush()
update_item_logs(item)
db.session.commit()
flash('A new item has been created!')
return redirect(url_for('show_user_page', uuid=uuid))
...
@app.route('/item/edit/<item_id>/<uuid>', methods=['POST'])
def edit_item(item_id, uuid):
"""アイテムを編集する
"""
...
try:
db.session.add(item)
update_item_logs(item)
db.session.commit()
flash('The item has been updated.')
return redirect(url_for('show_user_page', uuid=uuid))
...
@app.route('/item/delete/<item_id>/<uuid>')
def delete_item(item_id, uuid):
"""アイテムを削除する
item_idだけで削除できるとまずいので、uuidも渡す
"""
...
try:
db.session.add(item)
update_item_logs(item)
db.session.commit()
flash('The item has been deleted.')
return redirect(url_for('show_user_page', uuid=uuid))
これでFlashにメッセージが入った状態でViewを返すことができます。
secret keyの設定をしていない場合
ちなみに、config.pyでsecret keyの設定がされていないと、以下のようなエラーが出てしまいます。
RuntimeError
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
テンプレートファイルの変更
ビューにFlashの情報を渡せるようになったので、テンプレートファイルを変更し、渡された情報を表示するようにします。
Flashを使うのは基本的にアイテム一覧ページ(user_page)なので、user_page.htmlにget_flashed_messages()を入れます。
- user_page.html
{% extends "application.html" %}
{% block body %}
<div>
{% with messages = get_flashed_messages() %}
{% if messages %}
<div class='flash'>
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
</div>
{% endif %}
{% endwith %}
<h1>{{ title }}</h1>
<div class="field">
<p>My id is {{ page.id }}, uuid is {{ page.uuid }}.</p>
<p>Items : {{ page.items.count() }}</p>
</div>
...
- get_flashed_messages()でFlashメッセージのリストを取得
- with messages =としてmessagesにFlashリストを代入
- messagesがあれば、ループを回し、メッセージを表示する
という作りになっています。
動作確認
新規ページ作成
アイテム追加
アイテム編集
アイテム削除
それぞれの操作のあと、Flashメッセージが画面上部に表示されていることが分かります。
終わりに
これでFlashができました。
機能を作り込んでいきたいところですが、そろそろ見栄えも整えておきたいですね。
次回以降で見た目を少しマシにしていきたいと思います。
ディスカッション
コメント一覧
まだ、コメントがありません