【Python特化】おすすめのオンラインプログラミングスクール

【Python】Flaskによるルーティングの利用方法とテンプレート活用

flask-routing-and-templates

Flaskは、UIを持つアプリを実装するデザインパターンとしてMVTモデル(Model/View/Template)を採用してます。

MVTの役割
  • Model:ロジックを担当
  • View:入力を受け取りModelとTemplateを制御
  • Template:入出力を担当
flask-is-mvt-model

本記事では、FlaskのViewとTemplateを理解するために「ルーティング」と「テンプレート」について解説します。

目次

Flaskを利用するためのPython環境構築

PythonのWebフレームワークであるFlaskを利用するには、開発におけるPythonの環境構築が必要です。

Pythonの開発環境を構築するために、以下の手順を示します。

Flaskを利用するためのPython環境構築手順
  1. Pythonのダウンロードとインストール
  2. VSCode(Visual Studio Code)のインストール
  3. Flaskのインストール

PythonとVSCodeインストールがまだできていない人は「【Python】ダウンロードとインストール方法から環境構築まで解説!」を一読ください。

また、Flaskのインストールや開発環境構築がまだできていない人は、「【Python】フレームワークFlaskとは?インストール方法から開発環境構築まで解説!」を一読ください。

Flaskによるルーティングとは

Flaskにてルーティングを利用する場合、以下の基本的な使い方を理解しましょう。

Flaskにおけるルーティングの使い方
  • ルーティングを設定する
  • flask routesコマンドでルーティング情報を確認する
  • FlaskのEndpoint(エンドポイント)を設定する
  • Ruleに変数を設定する

それぞれの使い方を解説します。

Flaskによるルーティングを設定する

ルーティングとは、リクエスト先のURIと実際に処理する関数を紐づけることを指します。

Flaskでは、関数の先頭にデコレータと呼ばれる関数@app.route()を追加することでルートを追加できます。

ここでは、例としてapp.pyに「Good morning!」を出力するルートを追加します。

URIとは、http://127.0.0.5000/○○の○○の部分を指します。

# Flaskをインポート
from flask import Flask

# Flaskクラスをインスタンス化
app = Flask(__name__)

# URLと実行する関数をマッピング
@app.route("/")
def index():
    return 'Hello World!'

@app.route("/morning")
def morning():
    return 'Good morning!'

ターミナルにてflask runコマンドを実行し、http://127.0.0.5000/morningにアクセスするとGood morning!が表示されます。

flask routesコマンドでルーティング情報を確認する

ターミナルにてflask routesコマンドを実行し、ルーティング情報を確認してみましょう。

flask routes
Endpoint  Methods  Rule
--------  -------  -----------------------
index     GET      /
morning   GET      /morning
static    GET      /static/<path:filename>

上記のように、flask routesコマンドによって「Rule」「Methods」「Endpoint」の3要素が確認できます。

各要素がどのような役割を持っているか後述で解説します。

HTMLフォームで利用するHTTPメソッド

HTTPメソッドは、クライアントがサーバーに対してリクエストを送信する際、サーバーに実行してほしい処理を伝えるために利用します。

HTTPメソッドにはいくつか種類がありますが、ここではGETメソッドとPOSTメソッドを記載します。

スクロールできます
メソッド説明
GET検索や情報取得の場合に利用される。
POSTログインや問い合わせといったフォームの値を登録・更新などする場合に利用される。
HTTPメソッドの表

FlaskのEndpoint(エンドポイント)を設定する

Endpointは通常APIにアクセスするためのURIを指しますが、FlaskではURIと紐づけられた関数名を指します。

エンドポイント名は、以下の記述で任意で名付けられます。

@app.route("/", endpoint="endpoint-name")

例えば、先ほど追加した@app.route("/morning")にエンドポイント名を付与してみましょう。

@app.route("/morning", methods=["GET"], endpoint="morning-endpoint")
許可するHTTPメソッドを設定する

@app.routeといったデコレータ関数で許可するHTTPメソッドを指定できます。

@app.route("/morning", methods=["GET", "POST"])

上記のように、methodsにHTTPメソッド名を指定できます。

何も指定しない場合は、GETがデフォルトになります。

また、Flaskのバージョン2.0以降、route()を省略できます。

@app.get("/morning")
@app.post("/morning")

どちらを利用してもHTTPメソッドを指定することができます。

Ruleに変数を設定する

デコレータである@app.route()は、Ruleに変数を指定できます。

変数は、<変数名>の形式で指定します。

以下のようにコードを追加してみましょう。

# Flaskをインポート
from flask import Flask

# Flaskクラスをインスタンス化
app = Flask(__name__)

# URLと実行する関数をマッピング
@app.route("/")
def index():
    return 'Hello World!'

# /morning/<name>にすることで変数を指定
@app.route("/morning/<name>", methods=["GET", "POST"], endpoint="morning-endpoint")
# 関数の引数に変数であるnameを追加
def morning(name):
    # Python3.6から導入されたf-stringで変数を埋め込む
    return f'Good morning {name}!'

ターミナルにてflask routesコマンドを実行すると、以下のように「Rule」「Methods」「Endpoint」が書き換わります。

Endpoint          Methods    Rule
----------------  ---------  -----------------------
index             GET        /
morning-endpoint  GET, POST  /morning/<name>
static            GET        /static/<path:filename>

実際にターミナルにてflask runコマンドを実行し、http://127.0.0.5000/morning/jobcodeと入力します。

オプションでコンバーターと呼ばれる型定義を利用して<コンバーター:変数名>と記述し変数のデータ型も指定できます。

スクロールできます
コンバーターの型説明
stringスラッシュなしのテキスト
int正の整数
float正の浮動小数点
pathスラッシュ付きのテキスト許容
uuidUUID文字列
コンバーター表

UUID(Universally Unique Identifier)とは、ソフトウェア上でオブジェクトを一意に識別するための識別子です。

Flaskによるテンプレートとは

flask-is-mvt-model

Flaskにてテンプレートを利用する場合、以下の基本的な使い方を理解しましょう。

Flaskのテンプレートにおける使い方
  • テンプレートエンジンを利用する
  • テンプレート(templates)を作成する
  • Jinja2の基本的な使い方を理解する

それぞれの使い方を解説します。

Flaskによるテンプレートエンジンを利用する

テンプレートエンジンとは、テンプレート(templates)と呼ばれるひな形とデータを合成してHTMLファイルを出力するソフトウェアです。

Flaskのデフォルトテンプレートエンジンは、Jinja2が採用されています。

Flaskのインストールと同時に、Jinja2もインストールされています。

テンプレートエンジンを利用してHTMLをレンダリング(描画)するには、render_template関数を利用します。

テンプレート(templates)を作成する

レンダリングするために必要なテンプレートを作成します。

VSCodeにて任意のディレクトリ内にtemplatesディレクトリ(フォルダ)を作成し、templatesディレクトリ内にindex.htmlを作成します。

index.htmlには以下を記述します。

<!DOCTYPE html>
<html lang="ja">
   <head>
        <meta charset="utf-8">
        <title>Flask-sample</title>
  </head>
  <body>
	    <h1>Hello World!</h1>
  </body>
</html>

次に、app.pyにてrender_templateをインポートし、コードを修正します。

# rende_templateをインポート
from flask import Flask, render_template

# Flaskクラスをインスタンス化
app = Flask(__name__)

# URLと実行する関数をマッピング
@app.route("/")
def index():
    return render_template("index.html")

ターミナルにてflask runコマンドを実行し、http://127.0.0.5000/にアクセスしてみましょう。

render_template関数によって、templatesディレクトリ内のindex.html指定し読み込まれます。

Jinja2の基本的な使い方|変数/if文/for文

一般的にJinja2では、以下の基本的な使い方があります。

Jinja2の基本的な使い方
  • 変数の出力
  • 条件式if文
  • 繰り返しfor文

それぞれの基本的な使い方を解説する前に、上記の例で追加したmorning関数で利用するmorning.htmlを作成します。

上記で作成したtemplatesディレクトリ内にmorning.htmlを作成してみましょう。

変数の出力

変数の値を出力するには、.htmlファイルにて{{}}を使います。

また、render_template関数の第2引数以降で設定したキーワード引数あるいは辞書オブジェクトで指定した変数名が利用できます。

<!DOCTYPE html>
<html lang="ja">
   <head>
        <meta charset="utf-8">
        <title>Flask-sample</title>
  </head>
  <body>
	    <h1>Good morning {{ name }}!</h1>
  </body>
</html>
from flask import Flask, render_template

# Flaskクラスをインスタンス化
app = Flask(__name__)

# URLと実行する関数をマッピング
@app.route("/")
def index():
    return render_template("index.html")

# /morning/<name>にすることで変数を指定
@app.route("/morning/<name>", methods=["GET", "POST"], endpoint="morning-endpoint")
# 関数の引数に変数であるnameを追加
def morning(name):
    # render_template関数の第二引数としてキーワード引数を指定
    return render_template("morning.html", name=name)

ターミナルにてflask runコマンドを実行し、http://127.0.0.5000/morning/namenameの部分を任意で入力しアクセスしてみましょう。

render_template関数によって、templatesディレクトリ内のmorning.htmlが読み込まれ、指定した変数の値が出力されます。

条件式if文

次に、条件式if文を利用するには、{% %}を使います。

例えば、上記の変数出力のパターンで記述したmorning.htmlif文で書き換えてみます。

<!DOCTYPE html>
<html lang="ja">
   <head>
        <meta charset="utf-8">
        <title>Flask-sample</title>
  </head>
  <body>
        {% if name=="jobcode" %}
	    <h1>Good morning {{ name }}!</h1>
        {% else %}
        <h1>nameを変更してください。</h1>
        {% endif %}
  </body>
</html>

今回のケースは、変数nameが入力された際にアクセス可能な状態になるため、例として上記の条件分岐ができることを理解しておきましょう。

name=jobcodeを入力した場合
name=jobcode以外を入力した場合

繰り返しfor文

繰り返しfor文を利用する時も、{% %}を使います。

例えば、リストデータが存在した場合に以下の記述ができます。

<ul>
    {% for user in users %}
    <li><a href="{{ user.url }}">{{ user.username }}</a></li>
    {% endfor %}
</ui>

上記例のように、usersリストをfor文で繰り返し、各リストデータからurlusernameを取り出し表示させています。

Flaskによるルーティングの具体的な使い方

ユーザーが最もルーティングを利用する具体例の一つは、ログインフォーム入力後の画面遷移になります。

ここでは、具体例としてログイン認証機能を持つアプリを想定し、ログインフォーム入力後の画面遷移を実施します。

以下は、サンプルアプリとして開発したログイン認証アプリと画像保存アプリを連携させたディレクトリ構成になります。

flask-project
├── .env
├── apps
│   ├── app.py
│   ├── config.py
│   ├── static/css
│   │   └── bootstrap.min.css
│   ├── auth
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── models.py
│   │   ├── static/css
│   │   │   └── style.css
│   │   ├── templates
│   │   │   └── auth
│   │   │       ├── base.html
│   │   │       ├── index.html
│   │   │       ├── login.html
│   │   │       └── signup.html
│   │   └── views.py
│   ├── image
│   │   ├── __init__.py
│   │   ├── forms.py
│   │   ├── models.py
│   │   ├── static/css
│   │   │   └── style.css
│   │   ├── templates
│   │   │   └── image
│   │   │       ├── base.html
│   │   │       ├── index.html
│   │   │       └── upload.html
│   │   └── views.py
|   └── images
├── local.sqlite
└── migrations

本記事はルーティングを重点的に解説します。

Blueprintによってアプリを分割して開発しています。

Blueprintとは?

Blueprintとは、アプリケーションを分割するためのFlaskの拡張機能です。

Blueprintを利用すると、アプリケーション全体が大規模になっても簡潔な状態を保ち、アプリの保守性が向上します。

また、アプリを分割しているため1ファイルにおけるコードの可読性も高めます。

Blueprintのメリット
  • アプリケーション全体の保守性向上
  • 1ファイルにおけるコードの可読性向上

ディレクトリ構成が可視化しやすいため、開発効率も高まるメリットがあります。

Blueprintについて理解を深めたい人は「【Flask】Blueprintとは?使い方と実装方法を解説」を一読ください。

以下のコードは、ログイン認証機能を持つauthアプリのviews.pyになります。

また、ログインに関する関数のみ抜粋しています。

...省略...

# loginエンドポイントを作成する
@auth.route("/login", methods=["GET", "POST"])
def login():
    loginform = LoginForm()
    if loginform.validate_on_submit():
        # メールアドレスからユーザー取得
        user = User.query.filter_by(email=loginform.email.data).first()
        # ユーザーが存在しパスワード一致ならログイン許可
        if user is not None and user.verify_password(loginform.password.data):
            login_user(user)
            return redirect(url_for("image.index"))
        # ログイン失敗メッセージを設定する
        flash("メールアドレスかパスワードが不正です")
        
    return render_template("auth/login.html", form=loginform)

...省略...

ルーティングの流れとしては、ユーザー情報がDBの値と一致すればログインを許可する仕様になっています。

また、ログインが許可された場合に別アプリへリダイレクトしています。

リダイレクト時にurl_forにて"アプリ名.関数名"を設定することで指定した関数を処理できます。

ルーティングの動作確認

以下は、実際に作成したログイン画面になります。

ログインフォーム画面にて、必要なデータを入力しログインを試みます。

ログイン後、別アプリである画像一覧画面に遷移しました。

上記のように、分割したアプリ開発の中でルーティングは重要な概念です。

ログイン認証アプリに興味がある人は「【Flask】flask-loginによるログイン機能を実装した認証アプリ開発」を一読ください。

以下の内容を中心に解説しています。

ログイン認証アプリの要点
  • flask-loginの使い方を理解する
  • サインアップ/ログイン認証/ログアウト機能の実装方法を理解する
  • バリデーションチェックやデータベース操作を理解する

また、画像保存アプリに興味がある人は「【Flask】画像ファイルアップロード機能を実装した画像表示アプリ開発」を一読ください。

以下の内容を中心に解説しています。

画像保存アプリの要点
  • 画像ファイルアップロード機能の使い方を理解する
  • 画像と紐づくデータベース操作を理解する
  • 画像ファイルの表示方法と削除方法を理解する
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

sugiのアバター sugi SUGI

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code運営中

コメント

コメントする

目次