【Flask】Chapter2-3|url_for関数で動的リンクを生成しよう

ながみえ

一つ前のページではテンプレートの継承について学習しました。

今回は url_for()関数 について見ていきましょう。

Chapter1:Flask入門編
Chapter2:Jinja2入門編

 ・Chapter2-1:Jinja2とは何か|テンプレートエンジン入門
 ・Chapter2-2:テンプレートの継承を理解しよう
 ・Chapter2-3:url_for関数を理解しよう ◁今回はここ
 ・Chapter2-4:render_template関数を理解しよう
 ・Chapter2-5:テンプレートと繰り返し処理
 ・Chapter2-6:テンプレートと分岐処理
Chapter3:フィルター編
Chapter4:フォーム編
Chapter5:データベース編
Chapter6:エラーハンドリングとデバッグ編
Chapter7:アプリ開発編

FlaskでWebアプリを開発していると、「リンク先を指定する」場面に何度も遭遇します。

このときURLパスをそのままHTMLにベタ書きしてしまうと、後々のルート変更などでコードのメンテナンスがとても大変になります。

Flaskでは、この問題を解決するために url_for() という便利な関数が用意されており、ルーティングで定義した関数名から自動的に対応するURLパスを生成できます。

この記事では、url_for() の基本から使い方まで、初心者にもわかりやすく丁寧に解説していきます。

本記事は 有料記事(100円)ですが、現在は期間限定で無料公開中です。

<<前のページ

Flaskの記事一覧

次のページ>>

url_for()関数でリンクを動的生成する方法と基本構文

url_for()関数は、Flaskにおける「関数名からURLを生成する関数」です。

【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

url_for関数とは?|ルートに依存しないリンクを生成しよう

通常、HTMLでリンクを貼るときには以下のようにURLパスを直接書くことが多いです。

<a href="/hello">Helloページ</a>

しかしこの方法では、もしURLを /hello/greeting に変更したい場合、テンプレートファイル内のすべての /hello を修正しなければなりません。

そこで登場するのが url_for()関数です。

この関数を使えば、URLではなくルートに対応した「関数名」からURLを自動生成できるため、ルート変更にも柔軟に対応できます。

あわせて読みたい
【HTML】レッスン1-03:Webページにリンクや画像を挿入しよう
【HTML】レッスン1-03:Webページにリンクや画像を挿入しよう

url_forの基本構文と記述例

url_for関数は、Pythonコードとテンプレート内(Jinja2)にそれぞれ以下のように記載します。

from flask import url_for

url_for('関数名') # その関数のurlを生成
{{ url_for('関数名') }} <!-- その関数のurlを生成 -->

このように、url_for() には関数名を文字列として渡し、必要に応じてパラメータを指定します。

関数名は @app.route() で指定されたURLに対応しています。

例えば、以下のコードを見てみましょう。

from flask import Flask, url_for
app = Flask(__name__)

@app.route('/hello') # もしこのURLにアクセスされたら
def hello():         # hello関数の定義
    return 'Hello, Flask!'

with app.test_request_context(): # リクエストコンテキスト(詳細は後述)
    print(url_for('hello'))		 # hello関数のURL(/hello)を生成し、確認のため出力

このコードを実行すると、Hello関数にルーティングされたURL「/hello」が出力されます。

また、テンプレートの中でリンクを作るときも url_for() は非常に便利です。

<!-- hello関数のurlへリンク -->
<a href="{{ url_for('hello') }}">Helloページへ</a>

このように書くことで、ルートに対応するURLが自動的に挿入され、
<a href="/hello">Helloページへ</a> というHTMLが生成されます。

リクエストコンテキストとは?|app.test_request_context()メソッドを使おう

Flaskでは、requesturl_for などの一部のオブジェクトや関数は「リクエストコンテキスト」という特別な状態の中でしか正しく動作しません。

リクエストコンテキストとは、「今まさに誰かがこのアプリにアクセスしてきて、リクエストが処理されている状態」を指します。

Webアプリでは、多くの場合、ユーザーがページにアクセスしたとき自動的にリクエストコンテキストが作られます。そのため普段は意識しなくても問題ありません。

しかし、スクリプトや対話型シェル、学習中のテストコードなど「実際のリクエストが無い場面」でFlaskの機能を使いたい場合、このリクエストコンテキストを自分で用意する必要があります。

そこで使うのが、app.test_request_context()メソッド です。

with app.test_request_context():
    # ここでFlaskのrequestやurl_forなどが使える

このブロック内では一時的にリクエストが発生したのと同じ状態、すなわちリクエストコンテキストを作り出します。

この仕組みにより、たとえば

with app.test_request_context():
    print(url_for('hello'))

と書くと、実際にアクセスがなくてもurl_for('hello')が正しく動き、そのエンドポイントに対応するURL(例:/hello)を取得できます。

【Python】勉強猫がノートパソコンを見ながら考え込む様子。記事内の休憩用イラスト

引数を持つurl_for()関数の記述方法と注意点

もしURLに変数を含める場合は、ルーティング関数と合わせて url_for() にも引数を渡します。

@app.route('/user/<username>') # もしこのURLにアクセスされたら
def user_profile(username):    # 仮引数usernameを持つuser_profile関数の定義
    return f'ユーザー名: {username}'

with app.test_request_context(): # リクエストコンテキスト
    print(url_for('user_profile', username='taro')) # user_profil関数のURLを生成し、確認のため出力

このコードを実行すると、user_profile関数にルーティングされたURL「/user/taro」が出力されます。

テンプレート側でも以下のように使用できます。

<a href="{{ url_for('user_profile', username='taro') }}">Taroのプロフィール</a>

url_for()関数を使用することで、URLパスをテンプレートに直接書かなくてよいため保守性が大幅に向上します。

特にプロジェクトが大きくなってからの変更対応に大きなメリットがあります。

まとめ:url_forを使えばFlaskのリンク管理が圧倒的に楽になる

  • url_for() は関数名からURLを生成するFlaskの組み込み関数
  • Python側でもテンプレート側でも使用可能
  • 引数付きルートも柔軟に対応
  • 直接URLを書かず、保守性の高いコードを実現できる

次回は render_template() を使ってテンプレートにデータを渡す方法を学び、url_for() と組み合わせて実用的なページを作成していきます!

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいFlask学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

Flaskの記事一覧

次のページ>>

Q
サイト改善アンケート|1分だけ、ご意見をお聞かせください

本サイトでは、みなさまの学習をよりサポートできるサービスを目指しております。
そのため、ご利用者のみなさまの「プログラミングを学習する理由」などをアンケート形式でお伺いしています。

ご協力いただけますと幸いです。

アンケート
1.このサイトをどのように活用していますか?また、今後どのように活用したいですか?

FAQ|Flaskのurl_for関数の使い方でよくある質問

Q
Q1. url_for関数を使うとき、ルート関数名はどうやって決まるのですか?

基本的に、@app.route()でデコレートされた関数の名前が、そのままurl_for()で指定するルート関数名になります。関数名を変更すると、url_forでの指定も合わせて変える必要があります。

Q
Q2. テンプレート内でurl_forを使う場合、ファイルの拡張子は必要ですか?

url_forでは拡張子は指定不要です。テンプレートからPython側の関数にリンクを飛ばすときには、url_for('関数名')の形式で、HTMLファイルのパスではなくルート関数名を指定します。

Q
Q3. url_forを使って生成されたURLは絶対パスですか?相対パスですか?

url_forが生成するのは絶対パスです。ルート(”/”)からのパスとして扱われるため、異なるディレクトリ構造でもリンク切れしにくく、サイト構造が変わっても安定して使えます。

記事URLをコピーしました