1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

Fixed #10061 -- Added namespacing for named URLs - most importantly, for the admin site, where the absence of this facility was causing problems. Thanks to the many people who contributed to and helped review this patch.

This change is backwards incompatible for anyone that is using the named URLs
introduced in [9739]. Any usage of the old admin_XXX names need to be modified
to use the new namespaced format; in many cases this will be as simple as a
search & replace for "admin_" -> "admin:". See the docs for more details on
the new URL names, and the namespace resolution strategy.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@11250 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee
2009-07-16 16:16:13 +00:00
parent 9fd19c0161
commit 8d48eaa064
20 changed files with 544 additions and 119 deletions

View File

@@ -400,7 +400,7 @@ further processing.
.. versionadded:: 1.1
Another posibility is to include additional URL patterns not by specifying the
Another possibility is to include additional URL patterns not by specifying the
URLconf Python module defining them as the `include`_ argument but by using
directly the pattern list as returned by `patterns`_ instead. For example::
@@ -417,6 +417,13 @@ directly the pattern list as returned by `patterns`_ instead. For example::
(r'^credit/', include(extra_patterns)),
)
This approach can be seen in use when you deploy an instance of the Django
Admin application. The Django Admin is deployed as instances of a
:class:`AdminSite`; each :class:`AdminSite` instance has an attribute
``urls`` that returns the url patterns available to that instance. It is this
attribute that you ``included()`` into your projects ``urlpatterns`` when you
deploy the admin instance.
.. _`Django Web site`: http://www.djangoproject.com/
Captured parameters
@@ -439,6 +446,58 @@ the following example is valid::
In the above example, the captured ``"username"`` variable is passed to the
included URLconf, as expected.
.. _topics-http-defining-url-namespaces:
Defining URL Namespaces
-----------------------
When you need to deploying multiple instances of a single application, it can
be helpful to be able to differentiate between instances. This is especially
important when using _`named URL patterns <naming-url-patterns>`, since
multiple instances of a single application will share named URLs. Namespaces
provide a way to tell these named URLs apart.
A URL namespace comes in two parts, both of which are strings:
* An **application namespace**. This describes the name of the application
that is being deployed. Every instance of a single application will have
the same application namespace. For example, Django's admin application
has the somewhat predictable application namespace of ``admin``.
* An **instance namespace**. This identifies a specific instance of an
application. Instance namespaces should be unique across your entire
project. However, and instance namespace can be the same as the
application namespace. This is used to specify a default instance of an
application. For example, the default Django Admin instance has an
instance namespace of ``admin``.
URL Namespaces can be specified in two ways.
Firstly, you can provide the applicaiton and instance namespace as arguments
to the ``include()`` when you construct your URL patterns. For example,::
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
This will include the URLs defined in ``apps.help.urls`` into the application
namespace ``bar``, with the instance namespace ``foo``.
Secondly, you can include an object that contains embedded namespace data. If
you ``include()`` a ``patterns`` object, that object will be added to the
global namespace. However, you can also ``include()`` an object that contains
a 3-tuple containing::
(<patterns object>, <application namespace>, <instance namespace>)
This will include the nominated URL patterns into the given application and
instance namespace. For example, the ``urls`` attribute of Django's
:class:`AdminSite` object returns a 3-tuple that contains all the patterns in
an admin site, plus the name of the admin instance, and the application
namespace ``admin``.
Once you have defined namespace URLs, you can reverse them. For details on
reversing namespaced urls, see the documentation on :ref:`reversing namespaced
URLs <topics-http-reversing-url-namespaces>`.
Passing extra options to view functions
=======================================
@@ -613,6 +672,86 @@ not restricted to valid Python names.
name, will decrease the chances of collision. We recommend something like
``myapp-comment`` instead of ``comment``.
.. _topics-http-reversing-url-namespaces:
URL namespaces
--------------
.. versionadded:: 1.1
Namespaced URLs are specified using the `:` operator. For example, the main index
page of the admin application is referenced using ``admin:index``. This indicates
a namespace of ``admin``, and a named URL of ``index``.
Namespaces can also be nested. The named URL ``foo:bar:whiz`` would look for
a pattern named ``whiz`` in the namespace ``bar`` that is itself defined within
the top-level namespace ``foo``.
When given a namespaced URL (e.g.,, `myapp:index`) to resolve, Django splits
the fully qualified name into parts, and then tries the following lookup:
1. Django then looks for a matching application namespace (in this
example, ``myapp``). This will yield a list of instances of that
application.
2. If there is a ``current`` application defined, Django finds and returns
the URL resolver for that instance. The ``current`` can be specified
as an attribute on the template context - applications that expect to
have multiple deployments should set the ``current_app`` attribute on
any ``Context`` or ``RequestContext`` that is used to render a
template.
The current application can also be specified manually as an argument
to the :method:``reverse()`` function.
3. If there is no current application. Django looks for a default
application instance. The default application instance is the instance
that has an instance namespace matching the application namespace (in
this example, an instance of the ``myapp`` called ``myapp``)
4. If there is no default application instance, Django will pick the first
deployed instance of the application, whatever it's instance name may be.
5. If the provided namespace doesn't match an application namespace in
step 2, Django will attempt a direct lookup of the namespace as an
instance namespace.
If there are nested namespaces, these steps are repeated for each part of the
namespace until only the view name is unresolved. The view name will then be
resolved into a URL in the namespace that has been found.
To show this resolution strategy in action, consider an example of two instances
of ``myapp``: one called ``foo``, and one called ``bar``. ``myapp`` has a main
index page with a URL named `index`. Using this setup, the following lookups are
possible:
* If one of the instances is current - say, if we were rendering a utility page
in the instance ``bar`` - ``myapp:index`` will resolve to the index page of
the instance ``bar``.
* If there is no current instance - say, if we were rendering a page
somewhere else on the site - ``myapp:index`` will resolve to the first
registered instance of ``myapp``. Since there is no default instance,
the first instance of ``myapp`` that is registered will be used. This could
be ``foo`` or ``bar``, depending on the order they are introduced into the
urlpatterns of the project.
* ``foo:index`` will always resolve to the index page of the instance ``foo``.
If there was also a default instance - i.e., an instance named `myapp` - the
following would happen:
* If one of the instances is current - say, if we were rendering a utility page
in the instance ``bar`` - ``myapp:index`` will resolve to the index page of
the instance ``bar``.
* If there is no current instance - say, if we were rendering a page somewhere
else on the site - ``myapp:index`` will resolve to the index page of the
default instance.
* ``foo:index`` will again resolve to the index page of the instance ``foo``.
Utility methods
===============
@@ -624,7 +763,7 @@ your code, Django provides the following method (in the
``django.core.urlresolvers`` module):
.. currentmodule:: django.core.urlresolvers
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None)
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
``viewname`` is either the function name (either a function reference, or the
string version of the name, if you used that form in ``urlpatterns``) or the
@@ -646,6 +785,14 @@ vertical bar (``"|"``) character. You can quite happily use such patterns for
matching against incoming URLs and sending them off to views, but you cannot
reverse such patterns.
.. versionadded:: 1.1
The ``current_app`` argument allows you to provide a hint to the resolver
indicating the application to which the currently executing view belongs.
This ``current_app`` argument is used as a hint to resolve application
namespaces into URLs on specific application instances, according to the
:ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`.
.. admonition:: Make sure your views are all correct
As part of working out which URL names map to which patterns, the