mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Thanks Daniele Procida for review.
This commit is contained in:
		| @@ -2519,6 +2519,7 @@ own ``AdminSite`` instance since you will likely be importing all the per-app | ||||
| put ``'django.contrib.admin.apps.SimpleAdminConfig'`` instead of | ||||
| ``'django.contrib.admin'`` in your :setting:`INSTALLED_APPS` setting. | ||||
|  | ||||
| .. _multiple-admin-sites: | ||||
|  | ||||
| Multiple admin sites in the same URLconf | ||||
| ---------------------------------------- | ||||
|   | ||||
| @@ -578,11 +578,21 @@ URL namespaces | ||||
| Introduction | ||||
| ------------ | ||||
|  | ||||
| When you need to deploy multiple instances of a single application, it can be | ||||
| helpful to be able to differentiate between instances. This is especially | ||||
| important when using :ref:`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. | ||||
| URL namespaces allow you to uniquely reverse :ref:`named URL patterns | ||||
| <naming-url-patterns>` even if different applications use the same URL names. | ||||
| It's a good practice for third-party apps to always use namespaced URLs (as we | ||||
| did in the tutorial). Similarly, it also allows you to reverse URLs if multiple | ||||
| instances of an application are deployed. In other words, since multiple | ||||
| instances of a single application will share named URLs, namespaces provide a | ||||
| way to tell these named URLs apart. | ||||
|  | ||||
| Django applications that make proper use of URL namespacing can be deployed more | ||||
| than once for a particular site. For example :mod:`django.contrib.admin` has an | ||||
| :class:`~django.contrib.admin.AdminSite` class which allows you to easily | ||||
| :ref:`deploy more than once instance of the admin <multiple-admin-sites>`. | ||||
| In a later example, we'll discuss the idea of deploying the polls application | ||||
| from the tutorial in two different locations so we can serve the same | ||||
| functionality to two different audiences (authors and publishers). | ||||
|  | ||||
| A URL namespace comes in two parts, both of which are strings: | ||||
|  | ||||
| @@ -598,44 +608,43 @@ A URL namespace comes in two parts, both of which are strings: | ||||
|     This identifies a specific instance of an application. Instance namespaces | ||||
|     should be unique across your entire project. However, an 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 | ||||
|     default instance of an application. For example, the default Django admin | ||||
|     instance has an instance namespace of ``'admin'``. | ||||
|  | ||||
| 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'``. | ||||
| Namespaces can also be nested. The named URL ``'sports:polls:index'`` would | ||||
| look for a pattern named ``'index'`` in the namespace ``'polls'`` that is itself | ||||
| defined within the top-level namespace ``'sports'``. | ||||
|  | ||||
| .. _topics-http-reversing-url-namespaces: | ||||
|  | ||||
| Reversing namespaced URLs | ||||
| ------------------------- | ||||
|  | ||||
| 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: | ||||
| When given a namespaced URL (e.g. ``'polls:index'``) to resolve, Django splits | ||||
| the fully qualified name into parts and then tries the following lookup: | ||||
|  | ||||
| 1. First, Django looks for a matching :term:`application namespace` (in this | ||||
|    example, ``'myapp'``). This will yield a list of instances of that | ||||
|    example, ``'polls'``). 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* application 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. | ||||
|    attribute on any :class:`~django.template.Context` or | ||||
|    :class:`~django.template.RequestContext` that is used to render a template. | ||||
|  | ||||
|    The current application can also be specified manually as an argument | ||||
|    to the :func:`django.core.urlresolvers.reverse` function. | ||||
|    to the :func:`~django.core.urlresolvers.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 :term:`instance namespace` matching the :term:`application | ||||
|    namespace` (in this example, an instance of the ``myapp`` called | ||||
|    ``'myapp'``). | ||||
|    namespace` (in this example, an instance of ``polls`` called ``'polls'``). | ||||
|  | ||||
| 4. If there is no default application instance, Django will pick the last | ||||
|    deployed instance of the application, whatever its instance name may be. | ||||
| @@ -652,37 +661,73 @@ Example | ||||
| ~~~~~~~ | ||||
|  | ||||
| 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: | ||||
| of the ``polls`` application from the tutorial: one called ``'author-polls'`` | ||||
| and one called ``'publisher-polls'``. Assume we have enhanced that application | ||||
| so that it takes the instance namespace into consideration when creating and | ||||
| displaying polls. | ||||
|  | ||||
| * 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'``. | ||||
| .. snippet:: | ||||
|     :filename: urls.py | ||||
|  | ||||
|     from django.conf.urls import include, url | ||||
|  | ||||
|     urlpatterns = [ | ||||
|         url(r'^author-polls/', include('polls.urls', namespace='author-polls', app_name='polls')), | ||||
|         url(r'^publisher-polls/', include('polls.urls', namespace='publisher-polls', app_name='polls')), | ||||
|     ] | ||||
|  | ||||
| .. snippet:: | ||||
|     :filename: polls/urls.py | ||||
|  | ||||
|     from django.conf.urls import url | ||||
|  | ||||
|     from . import views | ||||
|  | ||||
|     urlpatterns = [ | ||||
|         url(r'^$', views.IndexView.as_view(), name='index'), | ||||
|         url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'), | ||||
|         ... | ||||
|     ] | ||||
|  | ||||
| Using this setup, the following lookups are possible: | ||||
|  | ||||
| * If one of the instances is current - say, if we were rendering the detail page | ||||
|   in the instance ``'author-polls'`` - ``'polls:index'`` will resolve to the | ||||
|   index page of the ``'author-polls'`` instance; i.e. both of the following will | ||||
|   result in ``"/author-polls/"``. | ||||
|  | ||||
|   In the method of a class-based view:: | ||||
|  | ||||
|     reverse('polls:index', current_app=self.request.resolver_match.namespace) | ||||
|  | ||||
|   and in the template: | ||||
|  | ||||
|   .. code-block:: html+django | ||||
|  | ||||
|     {% url 'polls:index' %} | ||||
|  | ||||
|   Note that reversing in the template requires the ``current_app`` be added as | ||||
|   an attribute to the template context like this:: | ||||
|  | ||||
|     def render_to_response(self, context, **response_kwargs): | ||||
|         response_kwargs['current_app'] = self.request.resolver_match.namespace | ||||
|         return super(DetailView, self).render_to_response(context, **response_kwargs) | ||||
|  | ||||
| * If there is no current instance - say, if we were rendering a page | ||||
|   somewhere else on the site - ``'myapp:index'`` will resolve to the last | ||||
|   registered instance of ``myapp``. Since there is no default instance, | ||||
|   the last 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. | ||||
|   somewhere else on the site - ``'polls:index'`` will resolve to the last | ||||
|   registered instance of ``polls``. Since there is no default instance | ||||
|   (instance namespace of ``'polls'``), the last instance of ``polls`` that is | ||||
|   registered will be used. This would be ``'publisher-polls'`` since it's | ||||
|   declared last in the ``urlpatterns``. | ||||
|  | ||||
| * ``'foo:index'`` will always resolve to the index page of the instance | ||||
|   ``'foo'``. | ||||
| * ``'author-polls:index'`` will always resolve to the index page of the instance | ||||
|   ``'author-polls'`` (and likewise for ``'publisher-polls'``) . | ||||
|  | ||||
| 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'``. | ||||
| If there were also a default instance - i.e., an instance named ``'polls'`` - | ||||
| the only change from above would be in the case where there is no current | ||||
| instance (the second item in the list above). In this case ``'polls:index'`` | ||||
| would resolve to the index page of the default instance instead of the instance | ||||
| declared last in ``urlpatterns``. | ||||
|  | ||||
| .. _namespaces-and-include: | ||||
|  | ||||
| @@ -693,17 +738,17 @@ URL namespaces of included URLconfs can be specified in two ways. | ||||
|  | ||||
| Firstly, you can provide the :term:`application <application namespace>` and | ||||
| :term:`instance <instance namespace>` namespaces as arguments to | ||||
| :func:`django.conf.urls.include()` when you construct your URL patterns. For | ||||
| :func:`~django.conf.urls.include()` when you construct your URL patterns. For | ||||
| example,:: | ||||
|  | ||||
|     url(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')), | ||||
|     url(r'^polls/', include('polls.urls', namespace='author-polls', app_name='polls')), | ||||
|  | ||||
| This will include the URLs defined in ``apps.help.urls`` into the | ||||
| :term:`application namespace` ``'bar'``, with the :term:`instance namespace` | ||||
| ``'foo'``. | ||||
| This will include the URLs defined in ``polls.urls`` into the | ||||
| :term:`application namespace` ``'polls'``, with the :term:`instance namespace` | ||||
| ``'author-polls'``. | ||||
|  | ||||
| Secondly, you can include an object that contains embedded namespace data. If | ||||
| you ``include()`` a list of :func:`django.conf.urls.url` instances, | ||||
| you ``include()`` a list of :func:`~django.conf.urls.url` instances, | ||||
| the URLs contained in that object will be added to the global namespace. | ||||
| However, you can also ``include()`` a 3-tuple containing:: | ||||
|  | ||||
| @@ -713,26 +758,27 @@ For example:: | ||||
|  | ||||
|     from django.conf.urls import include, url | ||||
|  | ||||
|     from app.helps import views | ||||
|     from . import views | ||||
|  | ||||
|     help_patterns = [ | ||||
|         url(r'^basic/$', views.basic), | ||||
|         url(r'^advanced/$', views.advanced), | ||||
|     polls_patterns = [ | ||||
|         url(r'^$', views.IndexView.as_view(), name='index'), | ||||
|         url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'), | ||||
|     ] | ||||
|  | ||||
|     url(r'^help/', include((help_patterns, 'bar', 'foo'))), | ||||
|     url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))), | ||||
|  | ||||
| This will include the nominated URL patterns into the given application and | ||||
| instance namespace. | ||||
|  | ||||
| For example, the Django Admin is deployed as instances of | ||||
| For example, the Django admin is deployed as instances of | ||||
| :class:`~django.contrib.admin.AdminSite`.  ``AdminSite`` objects have a ``urls`` | ||||
| attribute: A 3-tuple that contains all the patterns in the corresponding admin | ||||
| site, plus the application namespace ``'admin'``, and the name of the admin | ||||
| instance. It is this ``urls`` attribute that you ``include()`` into your | ||||
| projects ``urlpatterns`` when you deploy an Admin instance. | ||||
| projects ``urlpatterns`` when you deploy an admin instance. | ||||
|  | ||||
| Be sure to pass a tuple to ``include()``. If you simply pass three arguments: | ||||
| ``include(help_patterns, 'bar', 'foo')``, Django won't throw an error but due | ||||
| to the signature of ``include()``, ``'bar'`` will be the instance namespace and | ||||
| ``'foo'`` will be the application namespace instead of vice versa. | ||||
| ``include(polls_patterns, 'polls', 'author-polls')``, Django won't throw an | ||||
| error but due to the signature of ``include()``, ``'polls'`` will be the | ||||
| instance namespace and ``'author-polls'`` will be the application namespace | ||||
| instead of vice versa. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user