# Extracting URLs in Django Templates: `request.path` vs `path_info` vs `get_full_path` vs `build_absolute_uri` Often you need the current URL in a Django template. * Highlighting the active navigation item * Redirecting back to the original page after login (`next`) * Generating canonical URLs or share links * Creating a link that points to the *exact* current page, including query strings Besides `{{ request.path }}`, Django has a few similar attributes that can be confusing. Today we’ll cleanly compare the four most common ones: * `request.path` * `request.path_info` * `request.get_full_path()` * `request.build_absolute_uri()` --- ## Where does `{{ request }}` come from? {#sec-e3874691b2fc} If you see `{{ request }}` in a template, the **request context processor** is enabled. * `django.template.context_processors.request` injects the `request` object into the template context. * It is activated when added to `TEMPLATES` → `OPTIONS['context_processors']`. Django includes this processor by default, so you rarely need to change anything. The `request` object itself is an `HttpRequest` (actually a WSGI/ASGI subclass) created by Django when a request arrives and passed to the view. It contains attributes like `path` and `path_info`. ![Django the magician pulling tools out of a hat](/media/editor_temp/6/c112847e-a9ca-4d58-9a3f-076a20bfbef7.png) --- ## Quick Takeaway: How to remember the four attributes {#sec-0f722c9bd67c} * **`path`** – *Domain‑less path only* * **`path_info`** – *The real path the app sees (excluding any script prefix)* * **`get_full_path()`** – *`path` plus the query string* * **`build_absolute_uri()`** – *Full URL: scheme, host, path, and query string* Let’s dive into each one. --- ## 1) `request.path`: Path without the domain {#sec-26a629a2d24e} `request.path` returns the request path **without scheme or host**. Example: * `/music/bands/the_beatles/` ### When is it useful? {#sec-b307f735685f} * Simple comparisons for active menu items ```django {% if request.path == "/settings/" %}active{% endif %} ``` * Prefix checks like “which category is this page?” ```django {% if request.path|slice:":5" == "/api/" %}...{% endif %} ``` --- ## 2) `request.path_info`: The stable path in deployment environments {#sec-fd1e8e14948f} The key point from the Django docs is: * Some server configurations split the URL into a **script prefix** (`SCRIPT_NAME`) and **path info**. * `path_info` always contains the *path info* part, making it less dependent on the environment. In practice, if your app is mounted under a prefix like `/app` (reverse proxy, sub-path deployment, etc.), `path` and `path_info` can differ. ### When is it useful? {#sec-2985f0c9cd7c} * When you need the app‑relative path in a sub‑path deployment (e.g., `/app/`). * When the prefix may change between test and production. > On a single‑domain root (`/`), `path` and `path_info` are identical, so the difference is often unnoticed until the environment changes. --- ## 3) `request.get_full_path()`: Path plus query string {#sec-1364e4e65388} `get_full_path()` returns the **path plus the query string**. Example: * `/music/bands/the_beatles/?print=true` ### When is it useful? {#sec-0ac89fe1b7cd} * When you need a link that points to the *exact* current page for sharing, refreshing, or back‑navigation. ```django Refresh link ``` * When constructing a `next` parameter after login or permission checks. ```django Login ``` > Django also offers `get_full_path_info()`, which is based on `path_info`. It’s not covered here but worth knowing. --- ## 4) `request.build_absolute_uri()`: Full absolute URL with scheme and host {#sec-0ba80b4c4700} `build_absolute_uri()` builds an **absolute URI** from the current request. Typical output: * `https://example.com/music/bands/the_beatles/?print=true` ### When is it useful? {#sec-428d3d6b9613} * Email or messenger share links that require a full domain. * Canonical URLs, `og:url` meta tags. * Callback URLs for external systems. ### Things to watch out for {#sec-b24dccc132d6} `build_absolute_uri()` uses the host from the request (via `get_host()`), so it may not match the exact URL the browser used.In many cases the host matches, but if you’re behind Nginx reverse proxy or have custom tenant logic, the generated URL may differ from what the user sees. Always verify your deployment settings when using this method. --- ## Summary {#sec-bd7ea169a316} * **Active menu in templates** → `request.path` * **Stable comparison in sub‑path deployments** → `request.path_info` * **Include query string for “current page” links** → `request.get_full_path()` * **Full external link with domain** → `request.build_absolute_uri()` --- **Related posts**: - [What is a reverse proxy? Differences from forward proxy, purpose, and use cases](/whitedec/2025/12/10/reverse-proxy-forward-proxy-differences/) - [Learning Django from scratch: A roadmap starting with HTTP](/whitedec/2025/12/22/django-first-learning-roadmap/)