In Django, what is the difference between the app_name set in an app's urls.py and the namespace argument passed to include()?
answer
- two halves of a URL namespace
- shared by every mount
- unique per mount
- what the second defaults to
- colon-separated lookups
basics
~20 sapp_name is the application namespace, shared by every mount of that URLconf; include(..., namespace=...) is the instance namespace, identifying one mount. The instance defaults to app_name, and routes are looked up as 'namespace:name', such as 'comments:detail'.
solid answer
~40 sWithout namespaces every route name is global, so two apps that both name a route `list` collide and `reverse()` finds whichever pattern is last. Setting `app_name = 'comments'` in `comments/urls.py` puts its names under the **application namespace** `comments`, so code writes `'comments:detail'`. The `namespace=` argument to `include()` sets the **instance namespace**, which names one particular mount and must be unique in the project; when omitted it defaults to `app_name`, making that mount the default instance. Passing `namespace=` without any `app_name` raises `ImproperlyConfigured`; the app name can also come from an `include((patterns, 'comments'))` tuple. `request.resolver_match.app_name` and `.namespace` show both halves for the current request, and namespaces nest, as in `'forum:comments:detail'`.
go deeper
Recall that app_name in an app's urls.py lets you write names like 'comments:detail', and that this avoids clashes between apps.
Explain application versus instance namespace, the default of one to the other, the ImproperlyConfigured rule, and how nested lookups like 'forum:comments:detail' work.
Keep reusable apps on their application namespace, catch W005 duplicate instances, and debug 'not a registered namespace' errors back to a missing app_name or include().
Make app_name part of each app's public contract, since renaming it breaks every template and reverse() call in projects that mount the app.
## Why namespaces exist In Django, a route's `name=` is how code and templates build its URL. Without namespaces those names share one global pool. If the comments app names a route `list` and the events app does too, Django's documentation is explicit: the URL that `reverse()` finds depends on whichever pattern is last in the project's `urlpatterns`. Prefixing names by hand, such as `comments-list`, reduces the risk; **URL namespaces** remove it. ## The two halves A Django URL namespace has two parts, both strings: | Part | Set by | Scope | Example | |---|---|---|---| | **Application namespace** | `app_name` in the included URLconf, or the second item of an `include((patterns, app_name))` tuple | every mount of that URLconf | `comments` | | **Instance namespace** | `include(..., namespace='...')` | one mount; should be unique project-wide | `news-comments` | The application namespace says **which app** a route belongs to. The instance namespace says **which deployment** of it. When `namespace=` is omitted, the instance namespace defaults to the application namespace, and an instance whose instance namespace equals the app name is that app's **default instance**. ## Setting them 1. **The usual way:** `app_name = 'comments'` next to `urlpatterns` in `comments/urls.py`, and `path('comments/', include('comments.urls'))` in the root. Application namespace and instance namespace are both `comments`. 2. **Without a module:** `include((comment_patterns, 'comments'))`, useful when patterns are built in code. 3. **A named mount:** `include('comments.urls', namespace='news-comments')`. This requires an application namespace from one of the forms above; otherwise Django raises `ImproperlyConfigured`, saying a namespace without an `app_name` is not supported. 4. **The admin:** `admin.site.urls` supplies both at once, `admin` as the app and the site's name as the instance. ## Looking names up - A namespaced route is addressed with a colon: `'comments:detail'`. A bare `'detail'` searches only the global names and does not find it. - Namespaces nest. If a `forum` URLconf with `app_name = 'forum'` includes the comments URLconf, its routes are `'forum:comments:detail'`. - The first part of a lookup is tried as an application namespace, which may resolve to one of several instances; if no app has that name, it is tried as an instance namespace directly. - For the current request, `request.resolver_match.app_name` and `request.resolver_match.namespace` report the full application and instance namespaces, colon-joined when nested. ```python # comments/urls.py from django.urls import path from . import views app_name = 'comments' urlpatterns = [ path('', views.comment_list, name='list'), path('<int:pk>/', views.comment_detail, name='detail'), ] ``` ```python # a view elsewhere in the project from django.urls import reverse url = reverse('comments:detail', kwargs={'pk': 42}) # '/comments/42/' ``` ## Pitfalls - **Forgetting `app_name`.** Code that reverses `'comments:list'` then fails with `NoReverseMatch: 'comments' is not a registered namespace`. - **`namespace=` without `app_name`.** Raises `ImproperlyConfigured` when the URLconf loads. - **Reusing an instance namespace.** Two mounts with the same instance namespace trigger system check `urls.W005`, which warns that not every URL in it can be reversed. - **Writing the instance name inside the app.** A reusable app should reverse `'comments:...'`, its application namespace, and let Django pick the instance, never hardcode `'news-comments:...'`. - **Assuming the module path is the namespace.** Django never derives a namespace from `comments.urls`; only `app_name` or the tuple sets one. ## Diagnosing namespace errors The messages Django raises map directly to a cause: | Message or check | Usual cause | |---|---| | `NoReverseMatch: 'comments' is not a registered namespace` | the URLconf has no `app_name`, is not included, or is included from a different root URLconf | | `... is not a registered namespace inside 'forum'` | a nested lookup names an inner namespace the outer URLconf does not include | | `ImproperlyConfigured` about a namespace without an `app_name` | `namespace=` passed for a URLconf that sets no application namespace | | `urls.W005` namespace isn't unique | the same instance namespace used for two mounts | When the message names a namespace, check the included module first: an `app_name` line deleted or misspelled in a refactor is the most common cause. ## Choosing names Use the app's label as `app_name`, keep it stable because templates across the project depend on it, and reserve `namespace=` for the cases where the same URLconf is mounted more than once.
- In Django, how does code inside a view find out which namespace served the current request?Django sets `request.resolver_match` during resolution. Its `app_name` holds the application namespace, `namespace` the instance namespace, and `namespaces` the list of parts when namespaces are nested. A view shared by two mounts can use `namespace` to decide, for example, which section's comments to show.
- What is a default instance in Django's URL namespaces?It is the mount whose instance namespace equals the application namespace, which is what you get by including a URLconf with `app_name` and no `namespace=` argument. When a lookup such as `'comments:list'` has no current instance to go by, Django prefers the default instance.
saying these in an interview costs you the question
- When namespace= is omitted, the instance namespace defaults to the module path 'comments.urls'.
- include(..., namespace='x') works fine without any app_name.
- A bare 'detail' still finds a route that lives inside the comments namespace.
- Two apps can both name a route 'list' without namespaces and reverse() will raise an error.
- A reusable app should reverse its own URLs by their instance namespace.