Django 模板中取得 URL:request.path vs path_info vs get_full_path() vs build_absolute_uri()

在 Django 模板中,經常需要取得目前的 URL。

  • 導覽列「目前選單高亮」
  • 登入後「回到原本瀏覽的頁面(next)」
  • 建立 canonical URL / 共享連結
  • 包含查詢字串的「目前頁面不變」連結

然而除了 {{ request.path }},還有許多相似的屬性,容易混淆。今天我們將清楚比較以下四個:

  • 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 放入模板上下文。
  • 這個 context processor 會在 TEMPLATES 設定的 OPTIONS['context_processors'] 中註冊。

簡言之,Django 預設已將 request 加入全域上下文,除非開發者特意移除,使用者可以無縫使用。

request 物件本身是 Django 在接收請求時建立的 HttpRequest(實際上是 WSGI/ASGI 請求子類),並傳遞給視圖。這個物件包含 pathpath_info 等屬性。

Django 這位魔術師從帽子裡抽出工具的圖像


一句話結論:四個屬性如何記住?{#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 等子路徑(反向代理、子路徑部署)時,pathpath_info 可能不同。

何時有用?{#sec-2985f0c9cd7c}

  • 考慮子路徑部署(如 /app/)時,想以「應用程式基準路徑」判斷
  • 測試/正式環境前綴可能不同

若只在單一域名根目錄 (/) 運行,pathpath_info 通常相同;環境改變時差異才顯現。


3) request.get_full_path()path + 查詢字串{#sec-1364e4e65388}

get_full_path() 回傳 path 加上查詢字串 的值。範例:

  • /music/bands/the_beatles/?print=true

何時有用?{#sec-0ac89fe1b7cd}

  • 需要「目前頁面不變」的分享/重新整理/返回連結

django <a href="{{ request.get_full_path }}">重新整理連結</a> * 登入/權限檢查後回到原頁面時的 next

django <a href="/login/?next={{ request.get_full_path|urlencode }}">登入</a>

參考:Django 也有 get_full_path_info(),基於 path_info。雖非本比較範圍,但了解差異有助於選擇。


4) request.build_absolute_uri():包含協定與域名的「完整 URL」{#sec-0ba80b4c4700}

build_absolute_uri() 以目前請求為基礎,產生 絕對 URI

範例:

  • https://example.com/music/bands/the_beatles/?print=true

何時有用?{#sec-428d3d6b9613}

  • 需要域名的電子郵件/訊息分享連結
  • canonical URL、og:url 等 meta 標籤
  • 對外系統回呼 URL

注意事項{#sec-b24dccc132d6}

build_absolute_uri() 依賴請求的 Host 資訊(內部使用 get_host())。

  • 這並非實際請求 URL;若 Nginx 反向代理或 Django 中自訂 get_host(),產生的 URL 可能與瀏覽器實際 URL 不同。
  • 若實作了域名相關邏輯,請同時檢查部署設定,避免產生意外的域名/協定。

結論與摘要{#sec-bd7ea169a316}

  • 模板中菜單高亮request.path
  • 子路徑部署/代理環境下穩定比較request.path_info
  • 包含查詢字串的「目前頁面」request.get_full_path()
  • 對外完整連結(含域名)request.build_absolute_uri()

相關文章