python| まとめ | 現役エンジニア&プログラミングスクール講師「python」のまとめページです。pythonに関して抑えておきたい知識や文法やにについて記事をまとめています。まとめページの下部には「おすすめの学習書籍」「おすすめのITスクール情報」「おすすめ求人サイト」について情報を掲載中...

目標

  • Flaskのルーティングを利用した小規模アプリを作成できる。
  • テンプレートに処理の呼び出しを定義する。
  • フォームを利用できる。
  • リダイレクトを利用できる。
  • リクエストパラメータを利用できる。

フォームを利用できる。
フォームの利用については、formタグを利用したフォームの作成とapp.pyでのパラメータの取得についてを目標としています。※Flask-WTFなどの活用、バリデーションの実装は別の記事で扱う予定です。

Flaskのルーティングを利用した小規模アプリの作成

テンプレートに処理の呼び出しを定義する

前回の記事(Part.5)では次のページ遷移を行えるシステムを作成しました。

  • 商品管理ページと商品一覧ページは双方向へ遷移可能。
  • 商品管理ページと商品追加ページは双方向へ遷移可能。
  • 商品一覧ページと商品追加ページは双方向へ遷移可能。
  • 商品追加を行った後は商品一覧ページへリダイレクトされる。

テンプレートファイルの内容(アンカータグへのurl_for() 関数の設定)

ここでは以下の3つのテンプレートを「templates」ディレクトリに準備しました。

  • 商品管理ページ…manage_products.html
  • 商品一覧ページ…products.html
  • 商品追加ページ…add_product.html

この時、テンプレートでは、ページ遷移を行うために、アンカータグ(aタグ)の href属性 に url_for()関数を利用しました。

この、Flaskの url_for() 関数は、Flaskのルーティングで定義された関数(エンドポイント)に対応するURLを生成するためのものでした。アンカータグの href属性 で利用される場合は、この部分が適切なURLとして設定されます。

例えば、manage_products.html 内の href=”{{ url_for(‘product_list’) }}” の場合、Flaskのルーティングで定義されたエンドポイントに基づき、適切なURLが生成されることになり、今回の場合、app.pyファイル内で関数名が product_list でそれに対応するURLは、 /products なので、レンダリングされた時に、href=”/products” としてHTMLファイルで生成されることになります。

レンダリングされたファイルで、このタグをクリックするとFlaskのルーティングに従って、該当するproduct_list()関数が実行されることになります。FlaskのルーティングでRuleの部分がURLに該当します。

Flaskのルーティングを確認できる flask routes コマンド

Flaskのルーティングは次のコマンドで確認ができます。

(venv) C:\Users\user\Desktop\FlaskProj>flask routes

環境変数を有効化して「flask routes」コマンドを実行します。

# 仮想環境を有効化します。
C:\Users\user\Desktop\FlaskProj>.venv\Scripts\activate

# 仮想環境が有効化されます。
(venv) C:\Users\user\Desktop\FlaskProj>

# 仮想環境が有効化されます。
(venv) C:\Users\user\Desktop\FlaskProj>flask routes

次のような表が確認でいます。

manage_products.html(14,15行目)

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品管理</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

<body>
    <h1>商品管理ページ</h1>
    <ul>
        <li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧</a></li>
        <li><a href="{{ url_for('add_product') }}" class="button-link">商品追加</a></li>
    </ul>
</body>

</html>

add_product.html(15,16行目)

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品追加</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

<body>

    <h1>商品追加ページ</h1>
    <ul>
        <li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧に戻る</a></li>
        <li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
    </ul>

    <h1>商品追加フォーム</h1>

    <form method="POST" action="{{ url_for('add_product') }}">
        <label for="name">商品名</label>
        <input type="text" id="name" name="name" placeholder="商品名を入力" required>

        <label for="price">価格</label>
        <input type="number" id="price" name="price" placeholder="価格を入力" required>

        <input type="submit" value="商品を追加する">
    </form>

</body>

</html>

products.html(14,15行目)

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品一覧</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

<body>
    <h1>商品一覧ページ</h1>
    <ul>
        <li><a href="{{ url_for('add_product') }}" class="button-link">商品を追加する</a></li>
        <li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
    </ul>


    <h1>商品一覧</h1>
    <ul>
        {% for product in products %}
        <li>{{ product.name }} : ¥{{ "{:,}".format(product.price) }}</li>
        {% endfor %}
    </ul>

</body>

</html>

フォームを利用できる

フォームを利用できる。
フォームの利用については、formタグを利用したフォームの作成とapp.pyでのパラメータの取得についてを目標としています。※Flask-WTFなどの活用、バリデーションの実装は別の記事で扱います。

フォームに入力された値は、リクエスト(データの取得(≒ページの要求))と一緒にリクエストパラメーターとしてサーバー側に送られます。

送られた値はrequest.formオブジェクトに格納されます。

HTMLファイルとrequest.formオブジェクトから取り出した値をレンダリングしてユーザーにレスポンスします。

次のコードは、商品名と価格を入力し、POSTリクエストを/add_productに送信するためのものです。ここで、入力した商品名と価格は、サーバーに送信され、データベース(今回はpythonの辞書)に追加されます。

このフォームの、重要なポイントは、action=”{{ url_for(‘add_product’) }}”によって、適切なURLにデータが送信されること、そしてPOSTメソッドを使用してデータがサーバーに送信され、処理される点です。

商品の追加機能を実現するための重要なポイントにはつぎのものがあります。

method=”POST”(21行目)

フォームの送信方法がPOSTで指定されています(※指定しなければ送信方法はGETとなります)。基本的に、フォームを利用してデータを送信する場合はPOSTメソッドを使用します。

action=”{{ url_for(‘add_product’) }}”

action属性には、url_for(‘add_product’)が指定されています。url_for()は、Flaskのルートに定義されたエンドポイントadd_productに対応するURLを生成します。この場合、@app.route(“/add_product”, methods=[“GET”, “POST”])で定義されたadd_product関数が対応するURLとなります。
つまり、このフォームは/add_productにPOSTリクエストを送信し、商品追加の処理が行われることになります。

フォームフィールド(商品名と価格)

ユーザーから商品名と価格を入力してもらうための入力ボックスのことです。
required属性がついているため、これらのフィールドは必須入力項目となり、空のままフォームを送信することができません。

name属性

フォームで送信するデータの「キー名」を定義します。具体的には、フォームで送信するデータはname属性で決めた「キー名」と入力されたvalue「値」を、「キー名:値」のように、ひとつの対として送信します(例:address:東京都新宿区)。

Flaskでは、フォームから送信されたデータはrequest.formオブジェクトを通じてアクセスできます。例:address = request.form[‘address’]

type属性 の “submit”

フォームを送信するためのボタンです。ボタンをクリックすると、フォームのデータ(商品名と価格)がサーバーに送信されます。

add_product.html(21から29行目)

<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>商品追加</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
</head>

<body>

    <h1>商品追加ページ</h1>
    <ul>
        <li><a href="{{ url_for('product_list') }}" class="button-link">商品一覧に戻る</a></li>
        <li><a href="{{ url_for('manage_products') }}" class="button-link">商品管理ページ</a></li>
    </ul>

    <h1>商品追加フォーム</h1>

    <form method="POST" action="{{ url_for('add_product') }}">
        <label for="name">商品名</label>
        <input type="text" id="name" name="name" placeholder="商品名を入力" required>

        <label for="price">価格</label>
        <input type="number" id="price" name="price" placeholder="価格を入力" required>

        <input type="submit" value="商品を追加する">
    </form>

</body>

</html>

リダイレクトを利用できる

Flaskでリダイレクトを行う場合はredirectを利用します。redirectは、クライアントに別のページへの移動を指示するレスポンスを返します。つまり、ユーザーを新しいURLに自動的に移動させるために使用されます。Flaskでは、次のように使います。

redirect と url_for は、Flaskにおける「リダイレクト機能」と「URL生成機能」の重要なツールです。

return redirect(url_for("product_list"))

この行が意味することは、ユーザーが「商品追加フォーム」を送信した後に、product_listというエンドポイント(URL)にリダイレクトされるということです。リダイレクトによって、ユーザーは商品一覧ページに自動的に移動します。

リクエストパラメータを利用できる。

リクエストパラメータとは、ユーザーがフォームに入力したデータです。Flaskでは、requestオブジェクトを使ってリクエストパラメータにアクセスできます。例えば、ユーザーが「商品名」と「価格」を入力してフォームを送信した場合、そのデータはrequest.formを使って取得できます。

次のコードでは、ユーザーがフォームで送信した「商品名」と「価格」を取得しています

name = request.form["name"]
price = int(request.form["price"])
  • request.form[“name”]で、nameという名前のフォームフィールドのデータ(商品名)を取得します。
  • request.form[“price”]で、priceという名前のフォームフィールドのデータ(価格)を取得します。

request.formはフォームから送信されたデータを格納している辞書のようなオブジェクトです。このように、ユーザーから送信されたデータを簡単に取得できます。

POSTリクエストの処理の流れ

フォーム送信(POSTリクエスト)

ユーザーが商品名と価格を入力し、フォームを送信すると、POSTメソッドで/add_productにリクエストが送信されます。このとき、商品名と価格のデータがrequest.formに含まれることになります。

データの処理

サーバー側では、add_product関数内で次の処理が行われます。

  • request.form[“name”]で商品名を取得
  • request.form[“price”]で価格を取得し、int()で数値に変換
  • productsリストに新しい商品を追加

商品は、products.append({“id”: new_id, “name”: name, “price”: price})でリストに追加されます。新しい商品のidは、既存の商品の数を基に計算されます。

リダイレクト(redirect)

商品が追加されると、redirect(url_for(“product_list”))が実行され、ユーザーは商品一覧ページ(/products)にリダイレクトされます。リダイレクトは、URLの変更を伴い、ブラウザに新しいURLを表示させるために使用されます。

render_template(“products.html”, products=products)

render_template(“products.html”, products=products)のproducts=products部分は、FlaskのテンプレートエンジンであるJinja2に対してデータを渡すための部分です。この構文は、Pythonの変数productsをテンプレート内で使用できるようにするために使います。

render_template("products.html", products=products)

app.pyファイル

from flask import Flask, redirect, render_template, request, url_for

app = Flask(__name__)

# 商品リスト
products = [
    {"id": 1, "name": "オレンジジュース", "price": 140},
    {"id": 2, "name": "アップルジュース", "price": 150},
    {"id": 3, "name": "牛乳", "price": 180},
]


@app.route("/")
def index():
    return "Top page"


@app.route("/products")
def product_list():
    return render_template("products.html", products=products)


@app.route("/add_product", methods=["GET", "POST"])
def add_product():
    if request.method == "POST":
        # フォームから送られたデータを取得
        name = request.form["name"]
        price = int(request.form["price"])

        # 新しい商品を追加
        new_id = len(products) + 1
        products.append({"id": new_id, "name": name, "price": price})

        # 商品一覧ページにリダイレクト
        return redirect(url_for("product_list"))

    return render_template("add_product.html")


@app.route("/manage_products")
def manage_products():
    # 商品管理ページを表示
    return render_template("manage_products.html")


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

今回は以上になります。

「python」おすすめ書籍 ベスト3 | 現役エンジニア&プログラミングスクール講師「python」の学習でお勧めしたい書籍をご紹介しています。お勧めする理由としては、考え方、イメージなどを適切に捉えていること、「生のpython」に焦点をあてて解説をしている書籍であることなどが理由です。勿論、この他にも良い書籍はありますが、特に質の高かったものを選んで記事にしています。ページの下部には「おすすめのITスクール情報」「おすすめ求人サイト」について情報を掲載中。...

ブックマークのすすめ

「ほわほわぶろぐ」を常に検索するのが面倒だという方はブックマークをお勧めします。ブックマークの設定は別記事にて掲載しています。

「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】「お気に入り」の登録・削除方法【Google Chrome / Microsoft Edge】について解説している記事です。削除方法も掲載しています。...
【パソコン選び】失敗しないための重要ポイント | 現役エンジニア&プログラミングスクール講師【パソコン選び】失敗しないための重要ポイントについての記事です。パソコンのタイプと購入時に検討すべき点・家電量販店で見かけるCPUの見方・購入者が必要とするメモリ容量・HDDとSSDについて・ディスプレイの種類・バッテリーの持ち時間や保証・Officeソフト・ウィルス対策ソフトについて書いています。...