Python | 1 日 120 分 × 7 日アプリ学習:Flaskで作る超簡単Webアプリ(中級編)

Web APP Python
スポンサーリンク

3日目のゴール

3日目のテーマは
「Flaskのルーティングを“現場で使えるレベル”まで一段深くする」 ことです。

1日目:固定URL(/, /hello
2日目:動的URL(/user/<name>, /item/<int:id>

3日目ではここからさらに進んで、

URLの「?以降」(クエリパラメータ)を扱う
同じURLでも、処理を分けるイメージを持つ
url_for で「URLを文字列でベタ書きしない」感覚をつかむ

このあたりを、ちゃんと自分の言葉で説明できるところまで持っていきます。


復習:Flaskのルーティングの基本形

URL → 関数 → 返り値、という流れ

まずは、土台をもう一度確認します。

from flask import Flask

app = Flask(__name__)

@app.route("/")
def index():
    return "こんにちは Flask!"

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

ここで起きていることは、とてもシンプルです。

@app.route("/") で「/ に来たら index 関数を呼ぶ」と登録している。
ブラウザが http://127.0.0.1:5000/ にアクセスすると、Flaskが index を呼ぶ。
index が return した文字列が、そのままブラウザに返る。

2日目では、ここに「URLの一部を変数にする」という考え方を足しました。

@app.route("/user/<name>")
def show_user(name):
    return f"こんにちは、{name} さん!"

3日目では、「URLの?以降」も扱えるようにしていきます。


クエリパラメータとは何かをイメージでつかむ

?keyword=python&page=2 の「?以降」の世界

ブラウザで、こんなURLを見たことがあると思います。

https://example.com/search?keyword=python&page=2

? より前が「パス」
? より後ろが「クエリパラメータ」

クエリパラメータは、
「同じページだけど、条件を変えたいとき」に使われます。

検索キーワード
ページ番号
並び順

などを指定するのに、よく使われます。

Flaskでは、この「?以降」の値を request.args から取り出します。


request.args でクエリパラメータを読む

検索風のルートを作ってみる

まずは、シンプルな「検索っぽいページ」を作ってみましょう。

from flask import Flask, request

app = Flask(__name__)

@app.route("/search")
def search():
    keyword = request.args.get("keyword")
    page = request.args.get("page", default="1")

    if not keyword:
        return "検索キーワードを ?keyword=xxx の形で指定してください。"

    return f"検索キーワード: {keyword}, ページ: {page}"

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

ここでの重要ポイントを深掘りします。

from flask import request で「リクエスト情報」にアクセスできるようにしている。
request は「今来ているリクエスト」の情報を持っている特別なオブジェクトです。

request.args は「クエリパラメータ(?以降)」を表す。
request.args は辞書のように扱えます。
request.args.get("keyword")keyword の値を取り出せます。

get("page", default="1") のように、デフォルト値を指定できる。
page が指定されていないときは "1" を使う、という意味です。

ブラウザで次を試してみてください。

http://127.0.0.1:5000/search
http://127.0.0.1:5000/search?keyword=python
http://127.0.0.1:5000/search?keyword=flask&page=3

URLの「?以降」を変えるだけで、表示内容が変わる感覚をつかんでほしいです。


パスパラメータとクエリパラメータの違いを整理する

/user/1 と /user?id=1 の違い

2日目でやった「動的ルーティング」は、URLのパスの一部を変数にしました。

/user/1
/user/2

これは、ルート定義としてはこうでした。

@app.route("/user/<int:user_id>")
def show_user(user_id):
    ...
Python

一方、クエリパラメータを使うと、こういう形になります。

/user?id=1
/user?id=2

ルート定義は固定で、/user のままです。

@app.route("/user")
def show_user():
    user_id = request.args.get("id")
    ...
Python

どちらも「IDを指定する」という意味では似ていますが、
使い分けのイメージはこうです。

パスパラメータ(/user/1
「そのリソースそのもの」を表すことが多い。
ユーザー1のページ、記事10のページ、など。

クエリパラメータ(/search?keyword=python&page=2
「同じページだけど条件を変える」イメージ。
検索条件、ページ番号、並び順など。

今の段階では、
「どちらも使えるけど、意味合いが少し違う」
くらいの理解で十分です。


例題:ユーザー一覧+検索風ページを作る

/users と /users?name=xxx を同じ関数で処理する

2日目の「疑似ユーザーデータ」を使って、
クエリパラメータで絞り込みをしてみましょう。

from flask import Flask, request

app = Flask(__name__)

USERS = [
    {"id": 1, "name": "Taro"},
    {"id": 2, "name": "Hanako"},
    {"id": 3, "name": "Ken"},
    {"id": 4, "name": "Taroko"},
]

@app.route("/users")
def list_users():
    keyword = request.args.get("name")

    if not keyword:
        lines = ["全ユーザー一覧:"]
        for user in USERS:
            lines.append(f"{user['id']}: {user['name']}")
        return "<br>".join(lines)

    keyword_lower = keyword.lower()
    filtered = []
    for user in USERS:
        if keyword_lower in user["name"].lower():
            filtered.append(user)

    if not filtered:
        return f"'{keyword}' を含むユーザーは見つかりませんでした。"

    lines = [f"'{keyword}' を含むユーザー一覧:"]
    for user in filtered:
        lines.append(f"{user['id']}: {user['name']}")
    return "<br>".join(lines)

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

ここでの本質を整理します。

同じ /users というURLで、「全件表示」と「絞り込み表示」を両方やっている。
name パラメータがなければ全件表示。
name パラメータがあれば、その値で絞り込み。

request.args.get("name") で、クエリパラメータを受け取っている。
None や空文字のときは「指定なし」と判断している。

このパターンは、実際のWebアプリでもよく使います。
「同じページだけど、条件によって中身が変わる」という感覚を、ここでつかんでおきましょう。


url_for で「URLをベタ書きしない」感覚を持つ

URLを文字列で書くと、あとで必ずつらくなる

1日目・2日目では、リンクをこう書いていました。

return '<a href="/profile">プロフィール</a>'
Python

これは動きますが、
URLを文字列でベタ書きしているので、
あとでURLを変えたくなったときに、全部探して直す必要が出てきます。

Flaskには、
「関数名からURLを逆算してくれる」 url_for という便利な関数があります。

from flask import Flask, url_for

app = Flask(__name__)

@app.route("/")
def index():
    profile_url = url_for("profile")
    return f'<a href="{profile_url}">プロフィールへ</a>'

@app.route("/profile")
def profile():
    return "プロフィールページです。"

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

ここでの重要ポイントは、

url_for("profile") は、「profile 関数に対応するURL」を返す。
今は /profile ですが、もし将来ルートを /user/profile に変えても、
url_for("profile") を使っていれば、コードを直さなくて済みます。

url_for の引数は「関数名」である。
@app.route で登録した関数の名前を渡します。
文字列のURLではなく、「どの関数か」で指定するのがポイントです。

3日目の段階では、
「URLをベタ書きするより、url_for を使った方が後々楽になる」
という感覚だけ持っておけばOKです。


3日目のミニアプリ:簡易ユーザー検索サイト

仕様を言葉で整理する

/ トップページ:使い方の説明
/users:全ユーザー一覧
/users?name=xxx:名前に xxx を含むユーザーだけ表示
url_for を使ってリンクを作る

これを一つのファイルにまとめてみます。

from flask import Flask, request, url_for

app = Flask(__name__)

USERS = [
    {"id": 1, "name": "Taro"},
    {"id": 2, "name": "Hanako"},
    {"id": 3, "name": "Ken"},
    {"id": 4, "name": "Taroko"},
]

@app.route("/")
def index():
    users_url = url_for("list_users")
    return f"""
    <h1>ユーザー検索ミニアプリ</h1>
    <p><a href="{users_url}">ユーザー一覧を見る</a></p>
    <p>名前で絞り込みたいときは、URLの末尾に ?name=ta のように付けてください。</p>
    """

@app.route("/users")
def list_users():
    keyword = request.args.get("name")

    if not keyword:
        lines = ["<h2>全ユーザー一覧</h2>"]
        for user in USERS:
            lines.append(f"{user['id']}: {user['name']}")
        return "<br>".join(lines)

    keyword_lower = keyword.lower()
    filtered = []
    for user in USERS:
        if keyword_lower in user["name"].lower():
            filtered.append(user)

    if not filtered:
        return f"<h2>検索結果</h2>'{keyword}' を含むユーザーは見つかりませんでした。"

    lines = [f"<h2>検索結果: '{keyword}' を含むユーザー</h2>"]
    for user in filtered:
        lines.append(f"{user['id']}: {user['name']}")
    return "<br>".join(lines)

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

このミニアプリで、3日目のポイントが全部入っています。

クエリパラメータ(?name=xxx)を request.args.get で受け取る。
同じ /users というURLで、「全件表示」と「絞り込み表示」を切り替える。
url_for("list_users") で、URLを関数名から生成する。


3日目で絶対に押さえてほしい本質

「URLの“パス”と“?以降”を両方コントロールできる」

今日いちばん大事なのは、
Flaskのルーティングをこう説明できることです。

URLの「パス部分」(/users/1 のようなところ)は、
@app.route("/users/<int:id>") で変数として受け取れる。

URLの「?以降」(?name=xxx&page=2 のようなところ)は、
request.args.get("name")request.args.get("page") で受け取れる。

同じURLでも、クエリパラメータの有無や値によって、
返す内容を変えることができる。

そして、URLを文字列でベタ書きする代わりに、
url_for("関数名") で「関数からURLを逆算する」ことができる。

ここまで来たあなたは、
もう「Flaskでページを出せる人」ではなく、
「URL設計とパラメータ設計を意識してWebアプリを組み立てられる人」 です。

4日目以降は、
ここに「テンプレート(HTMLファイル)」や「フォーム送信(POST)」を重ねていきます。
でも、どれだけ機能が増えても、
今日やった「パス」と「クエリ」の扱い方が、ずっと土台になり続けます。

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