89点
# 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 はこのプロセッサをデフォルトで有効にしていることが多いので、特別に設定を触らなくても `{{ request }}` を自然に使えます。
`request` は、Django がリクエストを受け取ったときに生成する `HttpRequest`(実際には WSGI/ASGI のサブクラス)で、ビューへ渡されます。`path` や `path_info` などの属性もここに含まれます。

---
## ひと目で覚える 4 つの違い {#sec-0f722c9bd67c}
* **`path`**:ドメインなしのパスだけ
* **`path_info`**:アプリが見る「実際のパス」(script prefix を除外)
* **`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 prefix(`SCRIPT_NAME`)** と **path info** に分かれることがある
* `path_info` はそのうち **path info 部分を常に含む**ため、環境依存が少ない
例えばアプリを `/app` のようなプレフィックス配下にマウントする(リバースプロキシ、サブパスデプロイなど)構成では、`path` と `path_info` が異なることがあります。
### いつ役立つか {#sec-2985f0c9cd7c}
* サブパス配下で動く環境で、アプリ基準のパスとして扱いたいとき
* テストと本番でプレフィックスが変わる可能性があるとき
> ルート(`/`)直下で動かしている間は `path` と `path_info` が同じになりやすく、違いに気づきにくいです。
---
## 3) `request.get_full_path()`:パス + クエリ文字列 {#sec-1364e4e65388}
`get_full_path()` は **パスにクエリ文字列を含めたもの**を返します。
* `/music/bands/the_beatles/?print=true`
### いつ役立つか {#sec-0ac89fe1b7cd}
* 「現在のページそのまま」のリンクが必要なとき(共有、リフレッシュ、戻るなど)
```django
リフレッシュリンク
```
* ログインや権限チェック後に戻す `next` を作りたいとき
```django
ログイン
```
> なお Django には `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}
* メールやメッセンジャーなど、ドメイン付き URL が必要な共有リンク
* canonical URL、`og:url` などのメタタグ
* 外部システムへ渡すコールバック URL
### 注意すべき点 {#sec-b24dccc132d6}
`build_absolute_uri()` は、ホスト情報を `get_host()` から取得して URL を作ります。つまり、**ブラウザが実際に表示している URL と常に一致するとは限りません**。
特に次のような場合は要注意です。
* Nginx などのリバースプロキシ配下で Host/Proto ヘッダをどう渡しているかが環境次第
* テナント機構などで、アプリ側でホスト判定・書き換えロジックを持っている
ドメインやスキーム周りの設定(プロキシのヘッダ設定、Django 側の関連設定)も合わせて確認するのが安全です。
---
## まとめ {#sec-bd7ea169a316}
* **メニューのアクティブ判定** → `request.path`
* **サブパス配下でも安定して比較したい** → `request.path_info`
* **クエリ文字列まで含めて「現在のページそのまま」** → `request.get_full_path()`
* **外部に出す完全な URL(ドメイン込み)** → `request.build_absolute_uri()`
---
**関連記事**:
* [リバースプロキシとは?フォワードプロキシとの違い、目的、使用シナリオを一目で整理](/whitedec/2025/12/10/reverse-proxy-forward-proxy-differences/)
* [Django を最初から再学習する:HTTP から始める学習ロードマップ](/whitedec/2025/12/22/django-first-learning-roadmap/)