Commit 1e82094f authored by Marten Kenbeek's avatar Marten Kenbeek Committed by Tim Graham
Browse files

Fixed #21927 -- Made application and instance namespaces more distinct.

Made URL application namespaces be set in the included URLconf and
instance namespaces in the call to include(). Deprecated other ways
to set application and instance namespaces.
parent 39937de7
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -13,9 +13,9 @@ Including another URLconf
    1. Add an import:  from blog import urls as blog_urls
    2. Add a URL to urlpatterns:  url(r'^blog/', include(blog_urls))
"""
from django.conf.urls import include, url
from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^admin/', admin.site.urls),
]
+32 −4
Original line number Diff line number Diff line
@@ -5,7 +5,7 @@ from django.core.urlresolvers import (RegexURLPattern,
    RegexURLResolver, LocaleRegexURLResolver)
from django.core.exceptions import ImproperlyConfigured
from django.utils import six
from django.utils.deprecation import RemovedInDjango20Warning
from django.utils.deprecation import RemovedInDjango20Warning, RemovedInDjango21Warning


__all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']
@@ -19,11 +19,28 @@ handler500 = 'django.views.defaults.server_error'
def include(arg, namespace=None, app_name=None):
    if app_name and not namespace:
        raise ValueError('Must specify a namespace if specifying app_name.')
    if app_name:
        warnings.warn(
            'The app_name argument to django.conf.urls.include() is deprecated. '
            'Set the app_name in the included URLconf instead.',
            RemovedInDjango21Warning, stacklevel=2
        )

    if isinstance(arg, tuple):
        # callable returning a namespace hint
        try:
            urlconf_module, app_name = arg
        except ValueError:
            if namespace:
            raise ImproperlyConfigured('Cannot override the namespace for a dynamic module that provides a namespace')
                raise ImproperlyConfigured(
                    'Cannot override the namespace for a dynamic module that provides a namespace'
                )
            warnings.warn(
                'Passing a 3-tuple to django.conf.urls.include() is deprecated. '
                'Pass a 2-tuple containing the list of patterns and app_name, '
                'and provide the namespace argument to include() instead.',
                RemovedInDjango21Warning, stacklevel=2
            )
            urlconf_module, app_name, namespace = arg
    else:
        # No namespace hint - use manually provided namespace
@@ -32,6 +49,17 @@ def include(arg, namespace=None, app_name=None):
    if isinstance(urlconf_module, six.string_types):
        urlconf_module = import_module(urlconf_module)
    patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
    app_name = getattr(urlconf_module, 'app_name', app_name)
    if namespace and not app_name:
        warnings.warn(
            'Specifying a namespace in django.conf.urls.include() without '
            'providing an app_name is deprecated. Set the app_name attribute '
            'in the included module, or pass a 2-tuple containing the list of '
            'patterns and app_name instead.',
            RemovedInDjango21Warning, stacklevel=2
        )

    namespace = namespace or app_name

    # Make sure we can iterate through the patterns (without this, some
    # testcases will break).
+9 −0
Original line number Diff line number Diff line
@@ -70,6 +70,15 @@ details on these changes.
  ``django.utils.feedgenerator.RssFeed`` will be removed in favor of
  ``content_type``.

* The ``app_name`` argument to :func:`~django.conf.urls.include()` will be
  removed.

* Support for passing a 3-tuple as the first argument to ``include()`` will
  be removed.

* Support for setting a URL instance namespace without an application
  namespace will be removed.

.. _deprecation-removed-in-2.0:

2.0
+5 −5
Original line number Diff line number Diff line
@@ -293,15 +293,15 @@ with:

    urlpatterns = [
        url(r'^polls/', include('polls.urls')),
        url(r'^admin/', include(admin.site.urls)),
        url(r'^admin/', admin.site.urls),
    ]

.. admonition:: Doesn't match what you see?

    If you're seeing ``admin.autodiscover()`` before the definition of
    ``urlpatterns``, you're probably using a version of Django that doesn't
    match this tutorial version.  You'll want to either switch to the older
    tutorial or the newer Django version.
    If you're seeing ``include(admin.site.urls)`` instead of just
    ``admin.site.urls``, you're probably using a version of Django that
    doesn't match this tutorial version.  You'll want to either switch to the
    older tutorial or the newer Django version.

You have now wired an ``index`` view into the URLconf. Lets verify it's
working, run the following command:
+9 −7
Original line number Diff line number Diff line
@@ -442,18 +442,20 @@ view, and so might an app on the same project that is for a blog. How does one
make it so that Django knows which app view to create for a url when using the
``{% url %}`` template tag?

The answer is to add namespaces to your root URLconf. In the ``mysite/urls.py``
file, go ahead and change it to include namespacing:
The answer is to add namespaces to your  URLconf. In the ``polls/urls.py``
file, go ahead and add an ``app_name`` to set the application namespace:

.. snippet::
    :filename: mysite/urls.py
    :filename: polls/urls.py

    from django.conf.urls import include, url
    from django.contrib import admin
    from django.conf.urls import url

    app_name = 'polls'
    urlpatterns = [
        url(r'^polls/', include('polls.urls', namespace="polls")),
        url(r'^admin/', include(admin.site.urls)),
        url(r'^$', views.index, name='index'),
        url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
        url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
        url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
    ]

Now change your ``polls/index.html`` template from:
Loading