# Django テンプレートで URL を取得する方法:`request.path` vs `path_info` vs `get_full_path` vs `build_absolute_uri` Django テンプレートで現在の URL が必要になる場面は多々あります。 * ナビゲーションで「現在のメニューをアクティブ化」 * ログイン後に「元のページへ戻る(next)」 * canonical URL / 共有リンクを作成 * クエリストリングを含めて「現在のページそのまま」をリンクにする しかし `{{ request.path }}` 以外にも似たようなものがいくつかあるため、混乱しやすいです。 今日は混乱しやすい以下の 4 つを整理して比較します。 * `request.path` * `request.path_info` * `request.get_full_path()` * `request.build_absolute_uri()` --- ## `{{ request }}` はどこから来るのか {#sec-e3874691b2fc} テンプレートで `{{ request }}` が見えるということは、通常 **request context processor** が有効になっていることを意味します。 * `django.template.context_processors.request` が **テンプレートコンテキストに `request` を注入** します。 * このコンテキストプロセッサは `TEMPLATES` 設定の `OPTIONS['context_processors']` に登録されているときに動作します。 つまり、Django は `settings.TEMPLATES` に request をグローバルコンテキストとして入れるようにデフォルトで設定されているため、開発者が意図的にこの設定を削除しない限り、Django ユーザーは不便なく自然に使用できます。 そして `request` オブジェクト自体は、Django がリクエストを受け取るときに `HttpRequest`(実際には WSGI/ASGI リクエストサブクラス)を作成し、ビューまで渡すオブジェクトです。このオブジェクトには `path`、`path_info` などの属性が含まれます。 ![Djangoという名前のマジシャンがリクエスト帽子から道具を取り出すイメージ](/media/editor_temp/6/c112847e-a9ca-4d58-9a3f-076a20bfbef7.png) --- ## 一行結論:4 つを覚えると便利 {#sec-0f722c9bd67c} * **`path`**:ドメインを除いた「パスのみ」 * **`path_info`**:アプリが見る「実際のパス(スクリプトプレフィックス除外)」 * **`get_full_path()`**:`path` + クエリストリング * **`build_absolute_uri()`**:スキーム+ホスト+パスまで全て(完全な URL) それではそれぞれを正確に見ていきましょう。 --- ## 1) `request.path`:ドメインなしの「パス」 {#sec-26a629a2d24e} `request.path` は **ドメイン/スキームなし** でリクエストパスだけを返します。例は以下のような形です。 * `/music/bands/the_beatles/` ### いつ役立つか {#sec-b307f735685f} * メニューのアクティブ化など単純比較 ```django {% if request.path == "/settings/" %}active{% endif %} ``` * 「このページはどのカテゴリ?」といったプレフィックス比較 ```django {% if request.path|slice:":5" == "/api/" %}...{% endif %} ``` --- ## 2) `request.path_info`:デプロイ環境に左右されにくい「実際のパス」 {#sec-fd1e8e14948f} Django ドキュメントのポイントは次のとおりです。 * あるサーバ設定では URL パスが **スクリプトプレフィックス(SCRIPT_NAME)** と **path info** に分かれます。 * `path_info` はその中で **path info 部分を常に含む**(つまり環境に依存しにくい) 簡単に言えば、アプリが `/app` などのプレフィックス下にマウントされる構成(リバースプロキシ、サブパスデプロイなど)では `path` と `path_info` が異なる場合があります。 ### いつ役立つか {#sec-2985f0c9cd7c} * サブパスデプロイ(例:`/app/` 以下でサービス)などの環境を考慮し「アプリ基準のパス」で判断したいとき * テスト/本番サーバでプレフィックスが変わる場合 > 通常は単一ドメインルート(`/`)で動かすと `path` と `path_info` が同じになるため差を感じにくいです。 > しかし環境が変わると差が意味を持ちます。 --- ## 3) `request.get_full_path()`:`path` + クエリストリングまで {#sec-1364e4e65388} `get_full_path()` は **`path` にクエリストリングを付けた値** を返します。例は以下のような形です。 * `/music/bands/the_beatles/?print=true` ### いつ役立つか {#sec-0ac89fe1b7cd} * 「現在のページそのままを共有/リフレッシュ/戻る」リンクが必要なとき ```django リフレッシュリンク ``` * ログイン/権限チェック後に元のページへ戻る `next` を作るとき ```django ログイン ``` > ちなみに Django には `get_full_path()` 以外に `get_full_path_info()` もあります。 > 後者は `path_info` ベースで動作します。今日の比較対象はではありませんが、差を知っておくと便利です。 --- ## 4) `request.build_absolute_uri()`:スキーム+ドメインまで含む「完全な URL」 {#sec-0ba80b4c4700} `build_absolute_uri()` は現在のリクエストを基に **絶対 URL(absolute URI)** を作成します。 ざっくりこんな形になります。 * `https://example.com/music/bands/the_beatles/?print=true` ### いつ役立つか {#sec-428d3d6b9613} * メール/メッセンジャー共有リンクのように **ドメインが必須** な場合 * canonical URL、og:url などのメタタグ * 外部システムにコールバック URL を渡す ### 注意すべき点 {#sec-b24dccc132d6} `build_absolute_uri()` はホストを作る際にリクエストの Host 情報に依存します(内部的に `get_host()` を使用)。 **実際にブラウザから来た URL ではありません。** 多くの普通の状況では `get_host()` の値と実際の URL ドメインが一致することもありますが、Nginx がリバースプロキシである場合や Django ミドルウェアで開発者が意図的に `get_host()` の値を別のテナントホストに設定するロジックを作った場合、`{{ request.build_absolute_uri }}` の値が常に実際のブラウザ URL と一致するとは限りません。 したがって、nginx でも Django アプリ内部でもドメイン関連のロジックを実装している場合は、予想と異なるドメイン/スキームで生成される可能性があるので、デプロイ設定も併せて確認することをおすすめします。 --- ## 結論とまとめ {#sec-bd7ea169a316} * **テンプレートでメニューをアクティブ化** → `request.path` * **サブパスデプロイ/プロキシ環境まで安定して比較** → `request.path_info` * **クエリストリングまで含めて「現在のページそのまま」** → `request.get_full_path()` * **外部へ出る完全なリンク(ドメイン含む)** → `request.build_absolute_uri()` --- **関連記事を見る**: - [リバースプロキシとは?フォワードプロキシとの違い、目的、使用シナリオを一目で整理](/ko/whitedec/2025/12/10/reverse-proxy-forward-proxy-differences/) - [Django を最初から再学習する:HTTP から始める学習ロードマップ](/ko/whitedec/2025/12/22/django-first-learning-roadmap/)