【Flask】@app.routeでルーティングを設定する基本

Flask

こんにちは、かつコーチです。

前回、最小構成のFlaskアプリを動かしましたが、実際のWebアプリには複数のページやURLが必要です。

この記事では、Flaskの心臓部とも言える@app.routeの使い方を、パターン別に整理して解説します。

ルーティングとは?

URLと処理を結びつける仕組み

ルーティングとは、「どのURLにアクセスされたら、どの処理を実行するか」を決める仕組みのことです。

Flaskでは@app.routeというデコレータ(関数に機能を追加する目印のような書き方)を使って、URLと関数を紐付けます。

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "トップページ"

@app.route("/about")
def about():
    return "会社概要ページ"

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

このコードでは、/にアクセスするとindex関数が、/aboutにアクセスするとabout関数が呼ばれます。

なぜルーティングの理解が重要なのか

Webアプリは基本的に「URLごとに違う画面や機能を提供するもの」です。

ルーティングの書き方を理解していないと、ページが増えるたびにコードがどう動いているか分からなくなってしまいます。

逆に言えば、ルーティングさえ押さえれば、Flaskアプリの構造の半分は理解できたと言っても過言ではありません。

基本の書き方・実装手順

手順1: 複数HTTPメソッドに対応する

WebのリクエストにはGET(データを取得する)やPOST(データを送信する)などのHTTPメソッド(通信の種類)があります。

methods引数を指定することで、対応するメソッドを制御できます。

from flask import Flask, request

app = Flask(__name__)

@app.route("/contact", methods=["GET", "POST"])
def contact():
    if request.method == "POST":
        name = request.form.get("name")
        return f"{name}さん、送信ありがとうございます"
    return "お問い合わせフォームです"

methodsを指定しない場合、デフォルトではGETのみ受け付けます。

フォーム送信を扱う場合は、必ずPOSTを明記する必要があります。

手順2: 動的なURLパラメータを受け取る

URLの一部を変数として受け取りたい場合は、<変数名>という記法を使います。

@app.route("/users/<username>")
def show_user(username):
    return f"{username}さんのページです"

@app.route("/posts/<int:post_id>")
def show_post(post_id):
    return f"{post_id}番目の投稿です(型: {type(post_id).__name__})"

<int:post_id>のように型を指定すると、Flask側で自動的に整数に変換してくれます。

型を指定しない場合は文字列として扱われるので、数値計算をしたい場合はintfloatを明示しましょう。

手順3: リダイレクトとurl_forの活用

ページ移動を扱う際は、URLを直接文字列で書かず、url_for関数を使うのが定石です。

from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route("/old-page")
def old_page():
    return redirect(url_for("new_page"))

@app.route("/new-page")
def new_page():
    return "新しいページです"

url_for("new_page")は、関数名から対応するURLを自動生成してくれます。

URLの構造を後から変更する際、url_forを使っていれば関数名さえ変わらなければコード修正が不要になります。

つまずきやすい設定・注意点

末尾スラッシュの有無で挙動が変わる

Flaskは、ルート定義の末尾に/を付けるかどうかで挙動が異なります。

@app.route("/users/")
def users():
    return "ユーザー一覧"

このように末尾に/を付けた場合、/users(スラッシュなし)でアクセスすると自動的に/users/にリダイレクトされます。

逆に/users(スラッシュなし)で定義した場合、/users/(スラッシュあり)でアクセスすると404 Not Foundになります。

この違いを知らずに設計すると、後からURLの一貫性が崩れやすいので、プロジェクトの最初にルール(末尾スラッシュを付けるか統一する)を決めておくのがおすすめです。

よくあるつまずきポイント・エラー対処

同じ関数名を複数のルートで使ってエラーになる

❌ Before:異なるルートに同じ関数名を付けてしまい、アプリ起動時にAssertionError: View function mapping is overwriting an existing endpoint functionが出る

@app.route("/users")
def page():
    return "ユーザー一覧"

@app.route("/posts")
def page():  # 関数名が重複している
    return "投稿一覧"

✅ After:ルートごとに一意な関数名を付ける

@app.route("/users")
def user_list():
    return "ユーザー一覧"

@app.route("/posts")
def post_list():
    return "投稿一覧"

私自身、コピペでルートを増やしていったときにこのエラーに遭遇しました。

Flaskの関数名は単なる名前ではなく、url_forで参照する際のエンドポイント名(ルートを一意に識別するための名前)としても使われるため、重複が許されない仕様になっています。

int:を忘れて文字列比較になってしまう

❌ Before:<post_id>と型を指定せずに定義し、if post_id == 1:のような数値比較を書いてもFalseになってしまう(実際には文字列の”1″が渡ってくるため)

✅ After:<int:post_id>と型を指定して、Flask側で自動的に整数型に変換させる

型変換のミスは、エラーメッセージが出ずに「なぜか条件分岐が期待通りに動かない」という気づきにくいバグにつながるので要注意です。

応用・一歩先の使い方

Blueprintでルートを機能ごとに分割する

ルートの数が増えてくると、1つのapp.pyにすべて書くのは管理が大変になります。

FlaskにはBlueprintという、ルートを機能単位でファイル分割できる仕組みがあります。

from flask import Blueprint

user_bp = Blueprint("user", __name__)

@user_bp.route("/users")
def user_list():
    return "ユーザー一覧"

app.py側でapp.register_blueprint(user_bp)と登録することで、機能ごとにファイルを分けたまま1つのアプリとして動作させられます。

中規模以上のアプリを作る際に必須のテクニックなので、ルーティングに慣れてきたら挑戦してみてください。

まとめ

この記事のポイント

  • @app.routeはURLと処理を結びつけるFlaskの基本機能
  • methods引数でGET/POSTなどのHTTPメソッドを指定する
  • <int:xxx>のように型を指定して動的なURLパラメータを受け取れる
  • url_forを使うことでURL変更に強いコードになる
  • 関数名の重複はエラーの原因になるため一意な名前を付ける

次に読むべき記事

ルーティングの基本が分かったら、次は画面表示を担当する「Jinja2テンプレートでHTMLを動的に生成する」に進みましょう。

文字列を直接returnするのではなく、本格的なHTML画面を作れるようになります。


タグ: Flask, 初心者向け, フレームワーク基礎

タイトルとURLをコピーしました