Flaskによるflashメッセージの体験

# はじめに
Flaskにおけるflashメッセージの実装方法を説明します。
本記事では、フォームの値をサーバに送信し、その値によって表示するflashメッセージを変更するアプリを作成します。
こんな感じでflashメッセージを表示できるんだなぁ、くらいの理解ができることを目標とします。

# flashメッセージとは?
flashメッセージとは、**クライアントからサーバへリクエストを送信したとき、そのリクエストにより実行した処理が正常に終了したか否かをユーザに伝えるメッセージ**のことです。

多くの場合、webサービスを使用するユーザは、サーバサイドでどのような処理が実行されているか知りません。
そのため、自分が操作した内容が正常に処理されたのか失敗したのかを判断することができません。
そこで、flashメッセージを用いて、サーバサイドの処理をクライアントサイドに送信し、ユーザが処理状況を把握できるようにします。

## 例えば
以下のようなものがflashメッセージにあたります。
- 商品の購入に失敗しました。
- 登録に成功しました。

# 作成アプリイメージ
作成アプリでは、名前と年齢の入力欄を作成し、両方に値を入力して送信ボタンを押下した場合、登録成功のメッセージを表示します。
いずれかの入力欄が空の状態で送信ボタンを押下した場合、文字の入力を促すメッセージを表示します。
入力欄のチェックでは、値の有無のみを判定します。

- 入力あり
![flash_message_ok.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237378/a90ae37b-fb94-f20b-aab0-7d8922642468.gif)
- 入力なし
![flash_message_ng.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237378/96a3ba6d-552f-0e39-c15c-e48bea9693c3.gif)
  
## flashメッセージがない場合
flashメッセージを実装しない場合、処理結果がわからず、ユーザにとって不便なアプリとなってしまいます。
![なし_flash_message.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237378/b40bab44-0248-faa4-4828-805944a02735.gif)

# 実践
## 前提
- Flaskオブジェクトを生成できる
- リクエストを受け取る方法を知っている

## ディレクトリ構成
今回作成するアプリのフォルダ構成を確認します。
```terminal
├── app.py
└── templates
    └── index.html
```
- 「app.py」
    - ルーティング、flashメッセージの内容を記述します。
- 「index.html」
    - flashメッセージなどのブラウザの構造を記述します。

## ライブラリインストール
以下コマンドでライブラリをインストールします。
```terminal
pip install Flask
```
## ファイル作成
### app.py
以下を記述します。
```app.py
from flask import Flask, flash, render_template, request

app = Flask(__name__)
app.secret_key = 'secret_key'

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        name = request.form.get('name')
        age = request.form.get('age')
        
        if name and age:
            flash('登録に成功しました!')
            flash('これからよろしくお願いいたします!')
        else:
            flash('登録に失敗しました。')
            flash('名前・年齢を入力してください。')
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=True)
```
### 説明
```python
from flask import Flask, flash, render_template, request
```
- **flash**
    - flashメッセージを設定するモジュールです。

```python
app.secret_key = 'secret_key'
```
セッション情報を暗号化します。
今回は、簡易的に**secret_key**を値として指定しています。
この記述がない場合、flashメッセージを表示できず、エラーが発生します。

```python
if name and age:
    flash('登録に成功しました!')
    flash('これからよろしくお願いいたします!')
else:
    flash('登録に失敗しました。')
    flash('名前・年齢を入力してください。')
```
- **flash()**
    - 引数に指定した値をflashメッセージとして設定します。

本アプリでは、
クライアントから送信されたnameとageに値が入力されている場合、if以下の2行をflashメッセージとして設定します。
nameとageのいずれかに値が入力されていない場合、else以下の2行をflashメッセージとして設定します。

### index.html
以下を記述します。
```django:index.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <title>flash message test</title>
</head>

<body>
    <h1>登録画面</h1>

    {% with messages = get_flashed_messages() %}
    {% if messages %}
    <ul>
        {% for message in messages %}
        <li>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}
    {% endwith %}

    <form method="POST">
        <p>
            名前<br>
            <input type="text" name="name">
        </p>
        <p>
            年齢<br>
            <input type="text" name="age">
        </p>
        <input type="submit" value="送信">
    </form>
</body>

</html>
```
### 説明
```django
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
    {% for message in messages %}
    <li>{{ message }}</li>
    {% endfor %}
</ul>
{% endif %}
{% endwith %}
```
- **get_flashed_messages()**
    - サーバサイドで設定したflashメッセージを受け取ります。
    - 本アプリ内では、messagesにflaskメッセージを渡して、以降の処理で表示をしています。

# 終わりに
そこまで難しく考えることはなく「サーバでメッセージを設定して、クライアントで表示する」だけで実装ができました。
他にも、**get_flashed_messages()** の引数にパラメータを設定することで、メッセージの色を変更したり、表示するメッセージにフィルターをかけることもできるようです。
ひとまずは、本記事程度の内容を理解して、その都度必要な設定を調べていくのがよさそうです。

# 参考
- https://flask.palletsprojects.com/en/2.2.x/api/#flask.flash
- https://shigeblog221.com/flask-flash/