Flask

Pythonフレームワーク「Flask」を利用して複数画面をもつWebアプリケーションを作成してみた

Flaskとは、Pythonで開発する際のWebフレームワークの1つで、HTMLファイル内ではテンプレートエンジンである Jinja2を利用することで、条件に基づいて表示を分岐することができる。

今回は、入力画面・確認画面・完了画面の3画面を含み、HTMLオブジェクトとしてテキストボックス・ラジオボタン・チェックボックス等を含むWEBアプリケーションを作成してみたので、そのサンプルプログラムを共有する。

前提条件

下記記事のFlaskによる環境構築と実装が完了していること。

Pythonフレームワーク「Flask」を利用したWebアプリケーションを作成してみたFlaskは、Pythonで開発する際のWebフレームワークの1つで、マイクロフレームワーク(軽量で必要最低限の機能が搭載されているフレ...

サンプルプログラムの作成

作成したサンプルプログラムの構成は、以下の通り。
サンプルプログラムの構成
なお、上記の赤枠は、前提条件のプログラムから追加・変更したプログラムである。

input.htmlの内容は以下の通りで、入力画面を作成している。なお、(確認画面から戻ってきて)form_dataが存在する場合は、その値を表示するようにしている。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>入力画面</title>
</head>
<body>
  下記必要事項を記載の上、「確認」ボタンを押下してください。
  <br/><br/>
  <form action="/confirm" method="post">
    <table>
      <!-- 名前 -->
      <tr>
        <td align="left" valign="top">名前:</td>
        <td>
          <input type="text" id="name" name="name"
              {% if form_data %} value="{{ form_data.name }}" {% endif %} />
        </td>
      </tr>
      <!-- 生年月日 -->
      <tr>
        <td align="left" valign="top">生年月日:</td>
        <td>
          <input type="text" id="birthYear" name="birthYear" size="4" maxlength="4"
              {% if form_data %} value="{{ form_data.birthYear }}" {% endif %} />年
          <select name="birthMonth" id="birthMonth">
            <option value=""></option>
            {% for month in range(1, 12+1) %}
              <option value="{{ month }}"
                  {% if form_data and form_data.birthMonth == month|string %} selected {% endif %}>
                {{ month }}
              </option>
            {% endfor %}
          </select>月
          <select name="birthDay" id="birthDay">
            <option value=""></option>
            {% for day in range(1, 31+1) %}
              <option value="{{ day }}"
                  {% if form_data and form_data.birthDay == day|string %} selected {% endif %}>
                {{ day }}
              </option>
            {% endfor %}
          </select>日
        </td>
      </tr>
      <!-- 性別 -->
      <tr>
        <td align="left" valign="top">性別:</td>
        <td>
          <input type="radio" id="sex_1" name="sex" value="1"
              {% if form_data and form_data.sex=='1' %} checked {% endif %} />
          <label for="sex_1">男</label> 
          <input type="radio" id="sex_2" name="sex" value="2"
              {% if form_data and form_data.sex=='2' %} checked {% endif %} />
          <label for="sex_2">女</label>
        </td>
      </tr>
      <!-- メモ -->
      <tr>
        <td align="left" valign="top">メモ:</td>
        <td>
          <textarea rows="6" cols="40" id="memo" name="memo">{% if form_data %}{{ form_data.memo }}{% endif %}</textarea>
        </td>
      </tr>
      <!-- 入力確認 -->
      <tr>
        <td align="left" valign="top">入力確認:</td>
        <td>
          <input type="checkbox" id="checked" name="checked"
              {% if form_data and form_data.checked=='on' %} checked {% endif %} />
          <label for="checked">確認済</label>
        </td>
      </tr>
    </table>
    <br/><br/>
    <input type="submit" value="確認" />
  </form>
</body>
</html>

また、confirm.htmlの内容は以下の通りで、確認画面を作成している。入力画面の値を表示すると共に、他画面にhidden属性で各項目値を送信 できるようにしている。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <script src="../static/demo.js"></script>
  <title>確認画面</title>
</head>
<body>
  <p>入力内容を確認し、問題なければ「送信」ボタンを押下してください。</p>
  <form>
    <table border="0">
      <tr>
        <td align="left" valign="top">名前: </td>
        <td>{{ form_data.name }}</td>
      </tr>
      <tr>
        <td align="left" valign="top">生年月日: </td>
        <td>
          {% if form_data.birthYear != '' and form_data.birthMonth != '' and form_data.birthDay != '' %}
            {{ form_data.birthYear }}年{{ form_data.birthMonth }}月{{ form_data.birthDay }}日
          {% else %}
            不明
          {% endif %}
        </td>
      </tr>
      <tr>
        <td align="left" valign="top">性別: </td>
        <td>
          {% if form_data.sex == '1' %}
            男
          {% elif form_data.sex == '2' %}
            女
          {% else %}
            不明
          {% endif %}
        </td>
      </tr>
      <tr>
        <td align="left" valign="top">メモ: </td>
        <td>
          <!-- テキストエリアの改行コードを変換し、改行された状態で表示 -->
          {{ form_data.memo.replace("\r\n", "<br>") | safe }}
        </td>
      </tr>
      <tr>
        <td align="left" valign="top">確認チェック: </td>
        <td>
          {% if form_data.checked == 'on' %}
            確認済
          {% else %}
            未確認
          {% endif %}
        </td>
      </tr>
    </table>
    <br/><br/>
    <input type="button" value="送信" onclick="send()" /> 
    <input type="button" value="戻る" onclick="back()" />
    <!-- 次画面で利用できるよう、hidden属性で、入力画面の各項目値を送信 -->
    <input type="hidden" id="name" name="name" value="{{ form_data.name }}" />
    <input type="hidden" id="birthYear" name="birthYear" value="{{ form_data.birthYear }}" />
    <input type="hidden" id="birthMonth" name="birthMonth" value="{{ form_data.birthMonth }}" />
    <input type="hidden" id="birthDay" name="birthDay" value="{{ form_data.birthDay }}" />
    <input type="hidden" id="sex" name="sex" value="{{ form_data.sex }}" />
    <input type="hidden" id="memo" name="memo" value="{{ form_data.memo }}" />
    <input type="hidden" id="checked" name="checked" value="{{ form_data.checked }}" />
  </form>
</body>
</html>

さらにcomplete.htmlの内容は以下の通りで、完了画面を作成している。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>完了画面</title>
</head>
<body>
お申し込みが完了しました。
</body>
</html>

また、views.pyの内容は以下の通りで、各画面でボタンが押下された場合の処理を定義している。

from demo import app
from flask import render_template, request

# 初期表示処理
@app.route("/")
def index():
  return render_template("input.html")

# 確認画面遷移処理
@app.route("/confirm", methods=["POST"])
def confirm():
  return render_template("confirm.html", form_data=request.form)

# 確認画面_完了画面遷移処理
@app.route("/send", methods=["POST"])
def send():
  return render_template("complete.html")

# 確認画面_戻るボタン押下処理
@app.route("/back", methods=["POST"])
def back():
  return render_template("input.html", form_data=request.form)

さらに、demo.jsの内容は以下の通りで、確認画面で各ボタンが押下された場合の、views.py内のメソッド呼出を行っている。

'use strict';

// 確認画面_送信ボタン押下処理
function send(){
  let form = document.getElementsByTagName("form")[0];
  form.action="/send";
  form.method="post";
  form.submit();
}

// 確認画面_戻るボタン押下処理
function back(){
  let form = document.getElementsByTagName("form")[0];
  form.action="/back";
  form.method="post";
  form.submit();
}

その他のソースコード内容は、以下のサイトを参照のこと。
https://github.com/purin-it/python/tree/master/make-flask-web-somescreen/



フリエン(furien)は多くの案件を保有しフリーランス向けサービスも充実しているエージェントだったフリエン(furien)は、ITフリーランス(個人事業主)エンジニア専門のエージェントであるアン・コンサルティング株式会社が運営する業界...

サンプルプログラムの実行結果

サンプルプログラムの実行結果は、以下の通り。

1) コマンドプロンプトでserver.pyが入っているフォルダに移動し、server.pyを実行する。
サンプルプログラムの実行結果_1

2) Webブラウザで「http://127.0.0.1:5000/」とアクセスすると、以下のように、入力画面が表示される。
サンプルプログラムの実行結果_2

3) 以下のように、入力画面で各項目を指定し「確認」ボタンを押下すると、確認画面に入力画面の内容が表示される。さらに「戻る」ボタンを押下すると、入力画面に戻り入力値が復旧されることが確認できる。
サンプルプログラムの実行結果_3_1

サンプルプログラムの実行結果_3_2 サンプルプログラムの実行結果_3_3

4) 以下のように、メモを入力しないで「確認」ボタンを押下した場合も、確認画面に入力画面の内容が表示される。さらに「送信」ボタンを押下すると、完了画面に遷移することが確認できる。
サンプルプログラムの実行結果_4_1

サンプルプログラムの実行結果_4_2 サンプルプログラムの実行結果_4_3

要点まとめ

  • Flaskでのルーティング(リクエスト先のURIと実際に処理する関数を紐づけること)は、views.py内で@app.route()関数を利用することで実現できる。
  • Flask のHTMLファイル内ではテンプレートエンジンである Jinja2を利用することで、条件に基づいて表示を分岐することができる。