Browse Source

Fixed #22218 -- Deprecated django.conf.urls.patterns.

Thanks Carl Meyer for the suggestion and Alex Gaynor and Carl for reviews.
Tim Graham 11 years ago
parent
commit
d73d0e071c
100 changed files with 1008 additions and 928 deletions
  1. 3 3
      django/conf/project_template/project_name/urls.py
  2. 8 0
      django/conf/urls/__init__.py
  3. 17 4
      django/conf/urls/i18n.py
  4. 5 5
      django/conf/urls/static.py
  5. 3 3
      django/contrib/admin/options.py
  6. 11 11
      django/contrib/admin/sites.py
  7. 3 3
      django/contrib/admindocs/urls.py
  8. 4 5
      django/contrib/auth/admin.py
  9. 27 27
      django/contrib/auth/tests/urls.py
  10. 4 4
      django/contrib/auth/tests/urls_admin.py
  11. 12 12
      django/contrib/auth/urls.py
  12. 5 5
      django/contrib/flatpages/tests/urls.py
  13. 5 4
      django/contrib/flatpages/urls.py
  14. 3 3
      django/contrib/formtools/tests/urls.py
  15. 3 3
      django/contrib/formtools/tests/wizard/namedwizardtests/urls.py
  16. 3 3
      django/contrib/formtools/tests/wizard/wizardtests/urls.py
  17. 4 4
      django/contrib/gis/tests/geoadmin/urls.py
  18. 14 11
      django/contrib/gis/tests/geoapp/urls.py
  19. 7 7
      django/contrib/messages/tests/urls.py
  20. 14 13
      django/contrib/sitemaps/tests/urls/http.py
  21. 6 5
      django/contrib/sitemaps/tests/urls/https.py
  22. 4 4
      docs/howto/static-files/index.txt
  23. 5 0
      docs/internals/deprecation.txt
  24. 6 6
      docs/intro/overview.txt
  25. 12 12
      docs/intro/tutorial03.txt
  26. 3 3
      docs/intro/tutorial04.txt
  27. 9 10
      docs/ref/class-based-views/base.txt
  28. 21 21
      docs/ref/class-based-views/generic-date-based.txt
  29. 6 6
      docs/ref/class-based-views/generic-display.txt
  30. 3 3
      docs/ref/class-based-views/index.txt
  31. 19 19
      docs/ref/contrib/admin/index.txt
  32. 17 13
      docs/ref/contrib/flatpages.txt
  33. 14 14
      docs/ref/contrib/formtools/form-wizard.txt
  34. 3 3
      docs/ref/contrib/gis/tutorial.txt
  35. 21 17
      docs/ref/contrib/sitemaps.txt
  36. 4 3
      docs/ref/contrib/staticfiles.txt
  37. 9 9
      docs/ref/contrib/syndication.txt
  38. 39 10
      docs/ref/urls.txt
  39. 4 3
      docs/ref/views.txt
  40. 59 0
      docs/releases/1.8.txt
  41. 1 0
      docs/spelling_wordlist
  42. 9 9
      docs/topics/cache.txt
  43. 10 10
      docs/topics/class-based-views/generic-display.txt
  44. 3 3
      docs/topics/class-based-views/generic-editing.txt
  45. 12 12
      docs/topics/class-based-views/index.txt
  46. 11 11
      docs/topics/class-based-views/intro.txt
  47. 3 3
      docs/topics/class-based-views/mixins.txt
  48. 99 163
      docs/topics/http/urls.txt
  49. 27 20
      docs/topics/i18n/translation.txt
  50. 4 4
      tests/admin_changelist/urls.py
  51. 3 3
      tests/admin_custom_urls/models.py
  52. 4 4
      tests/admin_custom_urls/urls.py
  53. 10 10
      tests/admin_docs/urls.py
  54. 4 4
      tests/admin_inlines/urls.py
  55. 5 6
      tests/admin_scripts/urls.py
  56. 3 3
      tests/admin_views/admin.py
  57. 4 4
      tests/admin_views/customadmin.py
  58. 10 10
      tests/admin_views/urls.py
  59. 4 4
      tests/admin_widgets/urls.py
  60. 8 8
      tests/conditional_processing/urls.py
  61. 5 4
      tests/contenttypes_tests/urls.py
  62. 4 4
      tests/context_processors/urls.py
  63. 3 3
      tests/file_storage/urls.py
  64. 14 14
      tests/file_uploads/urls.py
  65. 3 3
      tests/forms_tests/urls.py
  66. 4 4
      tests/generic_inline_admin/urls.py
  67. 107 111
      tests/generic_views/urls.py
  68. 3 3
      tests/handlers/urls.py
  69. 4 4
      tests/i18n/patterns/urls/default.py
  70. 1 1
      tests/i18n/patterns/urls/disabled.py
  71. 3 3
      tests/i18n/patterns/urls/included.py
  72. 3 3
      tests/i18n/patterns/urls/namespace.py
  73. 2 3
      tests/i18n/patterns/urls/path_unused.py
  74. 1 1
      tests/i18n/patterns/urls/wrong.py
  75. 1 1
      tests/i18n/patterns/urls/wrong_namespace.py
  76. 11 4
      tests/i18n/urls.py
  77. 3 3
      tests/logging_tests/urls.py
  78. 4 4
      tests/middleware/cond_get_urls.py
  79. 6 6
      tests/middleware/extra_urls.py
  80. 6 6
      tests/middleware/urls.py
  81. 10 10
      tests/middleware_exceptions/urls.py
  82. 3 3
      tests/model_permalink/urls.py
  83. 4 4
      tests/proxy_models/urls.py
  84. 5 5
      tests/resolve_url/urls.py
  85. 3 3
      tests/servers/urls.py
  86. 5 4
      tests/staticfiles_tests/urls/default.py
  87. 18 18
      tests/syndication_tests/urls.py
  88. 4 4
      tests/template_tests/alternate_urls.py
  89. 7 8
      tests/template_tests/urls.py
  90. 31 31
      tests/test_client/urls.py
  91. 32 32
      tests/test_client_regress/urls.py
  92. 3 3
      tests/test_utils/tests.py
  93. 5 5
      tests/test_utils/urls.py
  94. 4 4
      tests/timezones/urls.py
  95. 3 3
      tests/urlpatterns_reverse/erroneous_urls.py
  96. 3 3
      tests/urlpatterns_reverse/extra_urls.py
  97. 4 4
      tests/urlpatterns_reverse/included_named_urls.py
  98. 3 3
      tests/urlpatterns_reverse/included_named_urls2.py
  99. 17 11
      tests/urlpatterns_reverse/included_namespace_urls.py
  100. 3 3
      tests/urlpatterns_reverse/included_no_kwargs_urls.py

+ 3 - 3
django/conf/project_template/project_name/urls.py

@@ -1,10 +1,10 @@
-from django.conf.urls import patterns, include, url
+from django.conf.urls import include, url
 from django.contrib import admin
 
-urlpatterns = patterns('',
+urlpatterns = [
     # Examples:
     # url(r'^$', '{{ project_name }}.views.home', name='home'),
     # url(r'^blog/', include('blog.urls')),
 
     url(r'^admin/', include(admin.site.urls)),
-)
+]

+ 8 - 0
django/conf/urls/__init__.py

@@ -1,9 +1,11 @@
 from importlib import import_module
+import warnings
 
 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
 
 
 __all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'patterns', 'url']
@@ -42,6 +44,12 @@ def include(arg, namespace=None, app_name=None):
 
 
 def patterns(prefix, *args):
+    warnings.warn(
+        'django.conf.urls.patterns() is deprecated and will be removed in '
+        'Django 2.0. Update your urlpatterns to be a list of '
+        'django.conf.urls.url() instances instead.',
+        RemovedInDjango20Warning, stacklevel=2
+    )
     pattern_list = []
     for t in args:
         if isinstance(t, (list, tuple)):

+ 17 - 4
django/conf/urls/i18n.py

@@ -1,6 +1,10 @@
+import warnings
+
 from django.conf import settings
 from django.conf.urls import patterns, url
 from django.core.urlresolvers import LocaleRegexURLResolver
+from django.utils import six
+from django.utils.deprecation import RemovedInDjango20Warning
 
 
 def i18n_patterns(prefix, *args):
@@ -8,14 +12,23 @@ def i18n_patterns(prefix, *args):
     Adds the language code prefix to every URL pattern within this
     function. This may only be used in the root URLconf, not in an included
     URLconf.
-
     """
-    pattern_list = patterns(prefix, *args)
+    if isinstance(prefix, (six.text_type, str)):
+        warnings.warn(
+            "Calling i18n_patterns() with the `prefix` argument and with tuples "
+            "instead of django.conf.urls.url() instances is deprecated and "
+            "will no longer work in Django 2.0. Use a list of "
+            "django.conf.urls.url() instances instead.",
+            RemovedInDjango20Warning, stacklevel=2
+        )
+        pattern_list = patterns(prefix, *args)
+    else:
+        pattern_list = [prefix] + list(args)
     if not settings.USE_I18N:
         return pattern_list
     return [LocaleRegexURLResolver(pattern_list)]
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^setlang/$', 'django.views.i18n.set_language', name='set_language'),
-)
+]

+ 5 - 5
django/conf/urls/static.py

@@ -1,7 +1,7 @@
 import re
 
 from django.conf import settings
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.core.exceptions import ImproperlyConfigured
 
 
@@ -12,9 +12,9 @@ def static(prefix, view='django.views.static.serve', **kwargs):
     from django.conf import settings
     from django.conf.urls.static import static
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ... the rest of your URLconf goes here ...
-    ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
     """
     # No-op if not in debug mode or an non-local prefix
@@ -22,6 +22,6 @@ def static(prefix, view='django.views.static.serve', **kwargs):
         return []
     elif not prefix:
         raise ImproperlyConfigured("Empty static prefix not permitted")
-    return patterns('',
+    return [
         url(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view, kwargs=kwargs),
-    )
+    ]

+ 3 - 3
django/contrib/admin/options.py

@@ -543,7 +543,7 @@ class ModelAdmin(BaseModelAdmin):
         return inline_instances
 
     def get_urls(self):
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         def wrap(view):
             def wrapper(*args, **kwargs):
@@ -552,13 +552,13 @@ class ModelAdmin(BaseModelAdmin):
 
         info = self.model._meta.app_label, self.model._meta.model_name
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^$', wrap(self.changelist_view), name='%s_%s_changelist' % info),
             url(r'^add/$', wrap(self.add_view), name='%s_%s_add' % info),
             url(r'^(.+)/history/$', wrap(self.history_view), name='%s_%s_history' % info),
             url(r'^(.+)/delete/$', wrap(self.delete_view), name='%s_%s_delete' % info),
             url(r'^(.+)/$', wrap(self.change_view), name='%s_%s_change' % info),
-        )
+        ]
         return urlpatterns
 
     def urls(self):

+ 11 - 11
django/contrib/admin/sites.py

@@ -177,12 +177,12 @@ class AdminSite(object):
             class MyAdminSite(AdminSite):
 
                 def get_urls(self):
-                    from django.conf.urls import patterns, url
+                    from django.conf.urls import url
 
                     urls = super(MyAdminSite, self).get_urls()
-                    urls += patterns('',
+                    urls += [
                         url(r'^my_view/$', self.admin_view(some_view))
-                    )
+                    ]
                     return urls
 
         By default, admin_views are marked non-cacheable using the
@@ -211,7 +211,7 @@ class AdminSite(object):
         return update_wrapper(inner, view)
 
     def get_urls(self):
-        from django.conf.urls import patterns, url, include
+        from django.conf.urls import url, include
         # Since this module gets imported in the application's root package,
         # it cannot import models from other applications at the module level,
         # and django.contrib.contenttypes.views imports ContentType.
@@ -226,7 +226,7 @@ class AdminSite(object):
             return update_wrapper(wrapper, view)
 
         # Admin-site-wide views.
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^$', wrap(self.index), name='index'),
             url(r'^login/$', self.login, name='login'),
             url(r'^logout/$', wrap(self.logout), name='logout'),
@@ -234,15 +234,15 @@ class AdminSite(object):
             url(r'^password_change/done/$', wrap(self.password_change_done, cacheable=True), name='password_change_done'),
             url(r'^jsi18n/$', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
             url(r'^r/(?P<content_type_id>\d+)/(?P<object_id>.+)/$', wrap(contenttype_views.shortcut), name='view_on_site'),
-        )
+        ]
 
         # Add in each model's views, and create a list of valid URLS for the
         # app_index
         valid_app_labels = []
         for model, model_admin in six.iteritems(self._registry):
-            urlpatterns += patterns('',
-                url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls))
-            )
+            urlpatterns += [
+                url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
+            ]
             if model._meta.app_label not in valid_app_labels:
                 valid_app_labels.append(model._meta.app_label)
 
@@ -250,9 +250,9 @@ class AdminSite(object):
         # labels for which we need to allow access to the app_index view,
         if valid_app_labels:
             regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
-            urlpatterns += patterns('',
+            urlpatterns += [
                 url(regex, wrap(self.app_index), name='app_list'),
-            )
+            ]
         return urlpatterns
 
     @property

+ 3 - 3
django/contrib/admindocs/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib.admindocs import views
 
-urlpatterns = patterns('',
+urlpatterns = [
     url('^$',
         views.BaseAdminDocsView.as_view(template_name='admin_doc/index.html'),
         name='django-admindocs-docroot'),
@@ -29,4 +29,4 @@ urlpatterns = patterns('',
     url('^templates/(?P<template>.*)/$',
         views.TemplateDetailView.as_view(),
         name='django-admindocs-templates'),
-)
+]

+ 4 - 5
django/contrib/auth/admin.py

@@ -1,5 +1,6 @@
 from django.db import transaction
 from django.conf import settings
+from django.conf.urls import url
 from django.contrib import admin
 from django.contrib.admin.options import IS_POPUP_VAR
 from django.contrib.auth.forms import (UserCreationForm, UserChangeForm,
@@ -76,11 +77,9 @@ class UserAdmin(admin.ModelAdmin):
         return super(UserAdmin, self).get_form(request, obj, **defaults)
 
     def get_urls(self):
-        from django.conf.urls import patterns
-        return patterns('',
-            (r'^(\d+)/password/$',
-             self.admin_site.admin_view(self.user_change_password))
-        ) + super(UserAdmin, self).get_urls()
+        return [
+            url(r'^(\d+)/password/$', self.admin_site.admin_view(self.user_change_password)),
+        ] + super(UserAdmin, self).get_urls()
 
     def lookup_allowed(self, lookup, value):
         # See #20078: we don't want to allow any lookups involving passwords.

+ 27 - 27
django/contrib/auth/tests/urls.py

@@ -1,4 +1,4 @@
-from django.conf.urls import patterns, url, include
+from django.conf.urls import url, include
 from django.contrib import admin
 from django.contrib.auth import context_processors
 from django.contrib.auth.forms import AuthenticationForm
@@ -70,36 +70,36 @@ def custom_request_auth_login(request):
     return login(request, authentication_form=CustomRequestAuthenticationForm)
 
 # special urls for auth test cases
-urlpatterns = urlpatterns + patterns('',
-    (r'^logout/custom_query/$', 'django.contrib.auth.views.logout', dict(redirect_field_name='follow')),
-    (r'^logout/next_page/$', 'django.contrib.auth.views.logout', dict(next_page='/somewhere/')),
-    (r'^logout/next_page/named/$', 'django.contrib.auth.views.logout', dict(next_page='password_reset')),
-    (r'^remote_user/$', remote_user_auth_view),
-    (r'^password_reset_from_email/$', 'django.contrib.auth.views.password_reset', dict(from_email='staffmember@example.com')),
-    (r'^password_reset/custom_redirect/$', 'django.contrib.auth.views.password_reset', dict(post_reset_redirect='/custom/')),
-    (r'^password_reset/custom_redirect/named/$', 'django.contrib.auth.views.password_reset', dict(post_reset_redirect='password_reset')),
-    (r'^password_reset/html_email_template/$', 'django.contrib.auth.views.password_reset', dict(html_email_template_name='registration/html_password_reset_email.html')),
-    (r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
+urlpatterns += [
+    url(r'^logout/custom_query/$', 'django.contrib.auth.views.logout', dict(redirect_field_name='follow')),
+    url(r'^logout/next_page/$', 'django.contrib.auth.views.logout', dict(next_page='/somewhere/')),
+    url(r'^logout/next_page/named/$', 'django.contrib.auth.views.logout', dict(next_page='password_reset')),
+    url(r'^remote_user/$', remote_user_auth_view),
+    url(r'^password_reset_from_email/$', 'django.contrib.auth.views.password_reset', dict(from_email='staffmember@example.com')),
+    url(r'^password_reset/custom_redirect/$', 'django.contrib.auth.views.password_reset', dict(post_reset_redirect='/custom/')),
+    url(r'^password_reset/custom_redirect/named/$', 'django.contrib.auth.views.password_reset', dict(post_reset_redirect='password_reset')),
+    url(r'^password_reset/html_email_template/$', 'django.contrib.auth.views.password_reset', dict(html_email_template_name='registration/html_password_reset_email.html')),
+    url(r'^reset/custom/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
         'django.contrib.auth.views.password_reset_confirm',
         dict(post_reset_redirect='/custom/')),
-    (r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
+    url(r'^reset/custom/named/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
         'django.contrib.auth.views.password_reset_confirm',
         dict(post_reset_redirect='password_reset')),
-    (r'^password_change/custom/$', 'django.contrib.auth.views.password_change', dict(post_change_redirect='/custom/')),
-    (r'^password_change/custom/named/$', 'django.contrib.auth.views.password_change', dict(post_change_redirect='password_reset')),
-    (r'^admin_password_reset/$', 'django.contrib.auth.views.password_reset', dict(is_admin_site=True)),
-    (r'^login_required/$', login_required(password_reset)),
-    (r'^login_required_login_url/$', login_required(password_reset, login_url='/somewhere/')),
-
-    (r'^auth_processor_no_attr_access/$', auth_processor_no_attr_access),
-    (r'^auth_processor_attr_access/$', auth_processor_attr_access),
-    (r'^auth_processor_user/$', auth_processor_user),
-    (r'^auth_processor_perms/$', auth_processor_perms),
-    (r'^auth_processor_perm_in_perms/$', auth_processor_perm_in_perms),
-    (r'^auth_processor_messages/$', auth_processor_messages),
-    (r'^custom_request_auth_login/$', custom_request_auth_login),
+    url(r'^password_change/custom/$', 'django.contrib.auth.views.password_change', dict(post_change_redirect='/custom/')),
+    url(r'^password_change/custom/named/$', 'django.contrib.auth.views.password_change', dict(post_change_redirect='password_reset')),
+    url(r'^admin_password_reset/$', 'django.contrib.auth.views.password_reset', dict(is_admin_site=True)),
+    url(r'^login_required/$', login_required(password_reset)),
+    url(r'^login_required_login_url/$', login_required(password_reset, login_url='/somewhere/')),
+
+    url(r'^auth_processor_no_attr_access/$', auth_processor_no_attr_access),
+    url(r'^auth_processor_attr_access/$', auth_processor_attr_access),
+    url(r'^auth_processor_user/$', auth_processor_user),
+    url(r'^auth_processor_perms/$', auth_processor_perms),
+    url(r'^auth_processor_perm_in_perms/$', auth_processor_perm_in_perms),
+    url(r'^auth_processor_messages/$', auth_processor_messages),
+    url(r'^custom_request_auth_login/$', custom_request_auth_login),
     url(r'^userpage/(.+)/$', userpage, name="userpage"),
 
     # This line is only required to render the password reset with is_admin=True
-    (r'^admin/', include(admin.site.urls)),
-)
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 4 - 4
django/contrib/auth/tests/urls_admin.py

@@ -2,7 +2,7 @@
 Test URLs for auth admins.
 """
 
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin, GroupAdmin
 from django.contrib.auth.models import User, Group
@@ -13,6 +13,6 @@ site = admin.AdminSite(name='auth_test_admin')
 site.register(User, UserAdmin)
 site.register(Group, GroupAdmin)
 
-urlpatterns = urlpatterns + patterns('',
-    (r'^admin/', include(site.urls)),
-)
+urlpatterns += [
+    url(r'^admin/', include(site.urls)),
+]

+ 12 - 12
django/contrib/auth/urls.py

@@ -3,17 +3,17 @@
 # It is also provided as a convenience to those who want to deploy these URLs
 # elsewhere.
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
+from django.contrib.auth import views
 
-urlpatterns = patterns('',
-    url(r'^login/$', 'django.contrib.auth.views.login', name='login'),
-    url(r'^logout/$', 'django.contrib.auth.views.logout', name='logout'),
-    url(r'^password_change/$', 'django.contrib.auth.views.password_change', name='password_change'),
-    url(r'^password_change/done/$', 'django.contrib.auth.views.password_change_done', name='password_change_done'),
-    url(r'^password_reset/$', 'django.contrib.auth.views.password_reset', name='password_reset'),
-    url(r'^password_reset/done/$', 'django.contrib.auth.views.password_reset_done', name='password_reset_done'),
+urlpatterns = [
+    url(r'^login/$', views.login, name='login'),
+    url(r'^logout/$', views.logout, name='logout'),
+    url(r'^password_change/$', views.password_change, name='password_change'),
+    url(r'^password_change/done/$', views.password_change_done, name='password_change_done'),
+    url(r'^password_reset/$', views.password_reset, name='password_reset'),
+    url(r'^password_reset/done/$', views.password_reset_done, name='password_reset_done'),
     url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
-        'django.contrib.auth.views.password_reset_confirm',
-        name='password_reset_confirm'),
-    url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete'),
-)
+        views.password_reset_confirm, name='password_reset_confirm'),
+    url(r'^reset/done/$', views.password_reset_complete, name='password_reset_complete'),
+]

+ 5 - 5
django/contrib/flatpages/tests/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 # special urls for flatpage test cases
-urlpatterns = patterns('',
-    (r'^flatpage_root', include('django.contrib.flatpages.urls')),
-    (r'^accounts/', include('django.contrib.auth.urls')),
-)
+urlpatterns = [
+    url(r'^flatpage_root', include('django.contrib.flatpages.urls')),
+    url(r'^accounts/', include('django.contrib.auth.urls')),
+]

+ 5 - 4
django/contrib/flatpages/urls.py

@@ -1,5 +1,6 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
+from django.contrib.flatpages import views
 
-urlpatterns = patterns('django.contrib.flatpages.views',
-    (r'^(?P<url>.*)$', 'flatpage'),
-)
+urlpatterns = [
+    url(r'^(?P<url>.*)$', views.flatpage),
+]

+ 3 - 3
django/contrib/formtools/tests/urls.py

@@ -2,12 +2,12 @@
 This is a URLconf to be loaded by tests.py. Add any URLs needed for tests only.
 """
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib.formtools.tests.tests import TestFormPreview
 
 from django.contrib.formtools.tests.forms import TestForm
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^preview/', TestFormPreview(TestForm)),
-)
+]

+ 3 - 3
django/contrib/formtools/tests/wizard/namedwizardtests/urls.py

@@ -1,4 +1,4 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib.formtools.tests.wizard.namedwizardtests.forms import (
     SessionContactWizard, CookieContactWizard, Page1, Page2, Page3, Page4)
 
@@ -18,9 +18,9 @@ def get_named_cookie_wizard():
         done_step_name='nwiz_cookie_done'
     )
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^nwiz_session/(?P<step>.+)/$', get_named_session_wizard(), name='nwiz_session'),
     url(r'^nwiz_session/$', get_named_session_wizard(), name='nwiz_session_start'),
     url(r'^nwiz_cookie/(?P<step>.+)/$', get_named_cookie_wizard(), name='nwiz_cookie'),
     url(r'^nwiz_cookie/$', get_named_cookie_wizard(), name='nwiz_cookie_start'),
-)
+]

+ 3 - 3
django/contrib/formtools/tests/wizard/wizardtests/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib.formtools.tests.wizard.wizardtests.forms import (
     SessionContactWizard, CookieContactWizard, Page1, Page2, Page3, Page4)
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^wiz_session/$', SessionContactWizard.as_view(
         [('form1', Page1),
          ('form2', Page2),
@@ -19,4 +19,4 @@ urlpatterns = patterns('',
          ('form3', Page3),
          ('form4', Page4)],
         template_name='other_wizard_form.html')),
-)
+]

+ 4 - 4
django/contrib/gis/tests/geoadmin/urls.py

@@ -1,6 +1,6 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 from django.contrib import admin
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 14 - 11
django/contrib/gis/tests/geoapp/urls.py

@@ -1,20 +1,23 @@
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns
+from django.conf.urls import url
+from django.contrib.gis import views as gis_views
+from django.contrib.sitemaps import views as sitemap_views
+from django.contrib.gis.sitemaps import views as gis_sitemap_views
 
 from .feeds import feed_dict
 from .sitemaps import sitemaps
 
 
-urlpatterns = patterns('',
-    (r'^feeds/(?P<url>.*)/$', 'django.contrib.gis.views.feed', {'feed_dict': feed_dict}),
-)
+urlpatterns = [
+    url(r'^feeds/(?P<url>.*)/$', gis_views.feed, {'feed_dict': feed_dict}),
+]
 
-urlpatterns += patterns('django.contrib.sitemaps.views',
-    (r'^sitemaps/(?P<section>\w+)\.xml$', 'sitemap', {'sitemaps': sitemaps}),
-)
+urlpatterns += [
+    url(r'^sitemaps/(?P<section>\w+)\.xml$', sitemap_views.sitemap, {'sitemaps': sitemaps}),
+]
 
-urlpatterns += patterns('django.contrib.gis.sitemaps.views',
-    (r'^sitemaps/kml/(?P<label>\w+)/(?P<model>\w+)/(?P<field_name>\w+)\.kml$', 'kml'),
-    (r'^sitemaps/kml/(?P<label>\w+)/(?P<model>\w+)/(?P<field_name>\w+)\.kmz$', 'kmz'),
-)
+urlpatterns += [
+    url(r'^sitemaps/kml/(?P<label>\w+)/(?P<model>\w+)/(?P<field_name>\w+)\.kml$', gis_sitemap_views.kml),
+    url(r'^sitemaps/kml/(?P<label>\w+)/(?P<model>\w+)/(?P<field_name>\w+)\.kmz$', gis_sitemap_views.kmz),
+]

+ 7 - 7
django/contrib/messages/tests/urls.py

@@ -1,4 +1,4 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib import messages
 from django.core.urlresolvers import reverse
 from django import forms
@@ -68,10 +68,10 @@ class ContactFormViewWithMsg(SuccessMessageMixin, FormView):
     success_message = "%(name)s was created successfully"
 
 
-urlpatterns = patterns('',
-    ('^add/(debug|info|success|warning|error)/$', add),
+urlpatterns = [
+    url('^add/(debug|info|success|warning|error)/$', add),
     url('^add/msg/$', ContactFormViewWithMsg.as_view(), name='add_success_msg'),
-    ('^show/$', show),
-    ('^template_response/add/(debug|info|success|warning|error)/$', add_template_response),
-    ('^template_response/show/$', show_template_response),
-)
+    url('^show/$', show),
+    url('^template_response/add/(debug|info|success|warning|error)/$', add_template_response),
+    url('^template_response/show/$', show_template_response),
+]

+ 14 - 13
django/contrib/sitemaps/tests/urls/http.py

@@ -1,5 +1,5 @@
 from datetime import datetime
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views
 from django.views.decorators.cache import cache_page
 
@@ -66,22 +66,23 @@ flatpage_sitemaps = {
     'flatpages': FlatPageSitemap,
 }
 
-urlpatterns = patterns('django.contrib.sitemaps.views',
-    (r'^simple/index\.xml$', 'index', {'sitemaps': simple_sitemaps}),
-    (r'^simple/custom-index\.xml$', 'index',
+
+urlpatterns = [
+    url(r'^simple/index\.xml$', views.index, {'sitemaps': simple_sitemaps}),
+    url(r'^simple/custom-index\.xml$', views.index,
         {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap_index.xml'}),
-    (r'^simple/sitemap-(?P<section>.+)\.xml$', 'sitemap',
+    url(r'^simple/sitemap-(?P<section>.+)\.xml$', views.sitemap,
         {'sitemaps': simple_sitemaps}),
-    (r'^simple/sitemap\.xml$', 'sitemap', {'sitemaps': simple_sitemaps}),
-    (r'^simple/custom-sitemap\.xml$', 'sitemap',
+    url(r'^simple/sitemap\.xml$', views.sitemap, {'sitemaps': simple_sitemaps}),
+    url(r'^simple/custom-sitemap\.xml$', views.sitemap,
         {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}),
-    (r'^empty/sitemap\.xml$', 'sitemap', {'sitemaps': empty_sitemaps}),
-    (r'^lastmod/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod_sitemaps}),
-    (r'^lastmod-mixed/sitemap\.xml$', 'sitemap', {'sitemaps': fixed_lastmod__mixed_sitemaps}),
-    (r'^generic/sitemap\.xml$', 'sitemap', {'sitemaps': generic_sitemaps}),
-    (r'^flatpages/sitemap\.xml$', 'sitemap', {'sitemaps': flatpage_sitemaps}),
+    url(r'^empty/sitemap\.xml$', views.sitemap, {'sitemaps': empty_sitemaps}),
+    url(r'^lastmod/sitemap\.xml$', views.sitemap, {'sitemaps': fixed_lastmod_sitemaps}),
+    url(r'^lastmod-mixed/sitemap\.xml$', views.sitemap, {'sitemaps': fixed_lastmod__mixed_sitemaps}),
+    url(r'^generic/sitemap\.xml$', views.sitemap, {'sitemaps': generic_sitemaps}),
+    url(r'^flatpages/sitemap\.xml$', views.sitemap, {'sitemaps': flatpage_sitemaps}),
     url(r'^cached/index\.xml$', cache_page(1)(views.index),
         {'sitemaps': simple_sitemaps, 'sitemap_url_name': 'cached_sitemap'}),
     url(r'^cached/sitemap-(?P<section>.+)\.xml', cache_page(1)(views.sitemap),
         {'sitemaps': simple_sitemaps}, name='cached_sitemap')
-)
+]

+ 6 - 5
django/contrib/sitemaps/tests/urls/https.py

@@ -1,4 +1,5 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
+from django.contrib.sitemaps import views
 
 from .http import SimpleSitemap
 
@@ -10,8 +11,8 @@ secure_sitemaps = {
     'simple': HTTPSSitemap,
 }
 
-urlpatterns = patterns('django.contrib.sitemaps.views',
-    (r'^secure/index\.xml$', 'index', {'sitemaps': secure_sitemaps}),
-    (r'^secure/sitemap-(?P<section>.+)\.xml$', 'sitemap',
+urlpatterns = [
+    url(r'^secure/index\.xml$', views.index, {'sitemaps': secure_sitemaps}),
+    url(r'^secure/sitemap-(?P<section>.+)\.xml$', views.sitemap,
         {'sitemaps': secure_sitemaps}),
-)
+]

+ 4 - 4
docs/howto/static-files/index.txt

@@ -94,9 +94,9 @@ this by adding the following snippet to your urls.py::
     from django.conf import settings
     from django.conf.urls.static import static
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ... the rest of your URLconf goes here ...
-    ) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+    ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
 
 .. note::
 
@@ -124,9 +124,9 @@ this by adding the following snippet to your urls.py::
     from django.conf import settings
     from django.conf.urls.static import static
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ... the rest of your URLconf goes here ...
-    ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
 .. note::
 

+ 5 - 0
docs/internals/deprecation.txt

@@ -15,6 +15,11 @@ about each item can often be found in the release notes of two versions prior.
 * ``cycle`` and ``firstof`` template tags will be removed from the ``future``
   template tag library (used during the 1.6/1.7 deprecation period).
 
+* ``django.conf.urls.patterns()`` will be removed.
+
+* Support for the ``prefix`` argument to
+  ``django.conf.urls.i18n.i18n_patterns()`` will be removed.
+
 .. _deprecation-removed-in-1.9:
 
 1.9

+ 6 - 6
docs/intro/overview.txt

@@ -184,13 +184,13 @@ to decouple URLs from Python code.
 Here's what a URLconf might look like for the ``Reporter``/``Article``
 example above::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
-        (r'^articles/(\d{4})/$', 'news.views.year_archive'),
-        (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
-        (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
-    )
+    urlpatterns = [
+        url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
+    ]
 
 The code above maps URLs, as simple `regular expressions`_, to the location of
 Python callback functions ("views"). The regular expressions use parenthesis to

+ 12 - 12
docs/intro/tutorial03.txt

@@ -92,13 +92,13 @@ In the ``polls/urls.py`` file include the following code:
 .. snippet::
     :filename: polls/urls.py
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
     from polls import views
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^$', views.index, name='index')
-    )
+    ]
 
 The next step is to point the root URLconf at the ``polls.urls`` module. In
 ``mysite/urls.py`` insert an :func:`~django.conf.urls.include`, leaving you
@@ -107,13 +107,13 @@ with:
 .. snippet::
     :filename: mysite/urls.py
 
-    from django.conf.urls import patterns, include, url
+    from django.conf.urls import include, url
     from django.contrib import admin
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^polls/', include('polls.urls')),
         url(r'^admin/', include(admin.site.urls)),
-    )
+    ]
 
 .. admonition:: Doesn't match what you see?
 
@@ -207,11 +207,11 @@ Wire these new views into the ``polls.urls`` module by adding the following
 .. snippet::
     :filename: polls/urls.py
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
     from polls import views
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ex: /polls/
         url(r'^$', views.index, name='index'),
         # ex: /polls/5/
@@ -220,7 +220,7 @@ Wire these new views into the ``polls.urls`` module by adding the following
         url(r'^(?P<question_id>\d+)/results/$', views.results, name='results'),
         # ex: /polls/5/vote/
         url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
-    )
+    ]
 
 Take a look in your browser, at "/polls/34/". It'll run the ``detail()``
 method and display whatever ID you provide in the URL. Try
@@ -583,13 +583,13 @@ it to include namespacing:
 .. snippet::
     :filename: mysite/urls.py
 
-    from django.conf.urls import patterns, include, url
+    from django.conf.urls import include, url
     from django.contrib import admin
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^polls/', include('polls.urls', namespace="polls")),
         url(r'^admin/', include(admin.site.urls)),
-    )
+    ]
 
 Now change your ``polls/index.html`` template from:
 

+ 3 - 3
docs/intro/tutorial04.txt

@@ -222,16 +222,16 @@ First, open the ``polls/urls.py`` URLconf and change it like so:
 .. snippet::
     :filename: polls/urls.py
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
     from polls import views
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^$', views.IndexView.as_view(), name='index'),
         url(r'^(?P<pk>\d+)/$', views.DetailView.as_view(), name='detail'),
         url(r'^(?P<pk>\d+)/results/$', views.ResultsView.as_view(), name='results'),
         url(r'^(?P<question_id>\d+)/vote/$', views.vote, name='vote'),
-    )
+    ]
 
 Amend views
 -----------

+ 9 - 10
docs/ref/class-based-views/base.txt

@@ -39,13 +39,13 @@ View
 
     **Example urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import MyView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^mine/$', MyView.as_view(), name='my-view'),
-        )
+        ]
 
     **Attributes**
 
@@ -131,13 +131,13 @@ TemplateView
 
     **Example urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import HomePageView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^$', HomePageView.as_view(), name='home'),
-        )
+        ]
 
     **Context**
 
@@ -192,17 +192,16 @@ RedirectView
 
     **Example urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
         from django.views.generic.base import RedirectView
 
         from article.views import ArticleCounterRedirectView, ArticleDetail
 
-        urlpatterns = patterns('',
-
+        urlpatterns = [
             url(r'^counter/(?P<pk>\d+)/$', ArticleCounterRedirectView.as_view(), name='article-counter'),
             url(r'^details/(?P<pk>\d+)/$', ArticleDetail.as_view(), name='article-detail'),
             url(r'^go-to-django/$', RedirectView.as_view(url='http://djangoproject.com'), name='go-to-django'),
-        )
+        ]
 
     **Attributes**
 

+ 21 - 21
docs/ref/class-based-views/generic-date-based.txt

@@ -65,16 +65,16 @@ ArchiveIndexView
 
     **Example myapp/views.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
         from django.views.generic.dates import ArchiveIndexView
 
         from myapp.models import Article
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^archive/$',
                 ArchiveIndexView.as_view(model=Article, date_field="pub_date"),
                 name="article_archive"),
-        )
+        ]
 
     **Example myapp/article_archive.html**:
 
@@ -166,15 +166,15 @@ YearArchiveView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import ArticleYearArchiveView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^(?P<year>\d{4})/$',
                 ArticleYearArchiveView.as_view(),
                 name="article_year_archive"),
-        )
+        ]
 
     **Example myapp/article_archive_year.html**:
 
@@ -261,11 +261,11 @@ MonthArchiveView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import ArticleMonthArchiveView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             # Example: /2012/aug/
             url(r'^(?P<year>\d{4})/(?P<month>[-\w]+)/$',
                 ArticleMonthArchiveView.as_view(),
@@ -274,7 +274,7 @@ MonthArchiveView
             url(r'^(?P<year>\d{4})/(?P<month>\d+)/$',
                 ArticleMonthArchiveView.as_view(month_format='%m'),
                 name="archive_month_numeric"),
-        )
+        ]
 
     **Example myapp/article_archive_month.html**:
 
@@ -355,16 +355,16 @@ WeekArchiveView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import ArticleWeekArchiveView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             # Example: /2012/week/23/
             url(r'^(?P<year>\d{4})/week/(?P<week>\d+)/$',
                 ArticleWeekArchiveView.as_view(),
                 name="archive_week"),
-        )
+        ]
 
     **Example myapp/article_archive_week.html**:
 
@@ -469,16 +469,16 @@ DayArchiveView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import ArticleDayArchiveView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             # Example: /2012/nov/10/
             url(r'^(?P<year>\d{4})/(?P<month>[-\w]+)/(?P<day>\d+)/$',
                 ArticleDayArchiveView.as_view(),
                 name="archive_day"),
-        )
+        ]
 
     **Example myapp/article_archive_day.html**:
 
@@ -543,15 +543,15 @@ TodayArchiveView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from myapp.views import ArticleTodayArchiveView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^today/$',
                 ArticleTodayArchiveView.as_view(),
                 name="archive_today"),
-        )
+        ]
 
     .. admonition:: Where is the example template for ``TodayArchiveView``?
 
@@ -593,14 +593,14 @@ DateDetailView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
         from django.views.generic.dates import DateDetailView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^(?P<year>\d+)/(?P<month>[-\w]+)/(?P<day>\d+)/(?P<pk>\d+)/$',
                 DateDetailView.as_view(model=Article, date_field="pub_date"),
                 name="archive_date_detail"),
-        )
+        ]
 
     **Example myapp/article_detail.html**:
 

+ 6 - 6
docs/ref/class-based-views/generic-display.txt

@@ -54,13 +54,13 @@ DetailView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from article.views import ArticleDetailView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^(?P<slug>[-_\w]+)/$', ArticleDetailView.as_view(), name='article-detail'),
-        )
+        ]
 
     **Example myapp/article_detail.html**:
 
@@ -123,13 +123,13 @@ ListView
 
     **Example myapp/urls.py**::
 
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         from article.views import ArticleListView
 
-        urlpatterns = patterns('',
+        urlpatterns = [
             url(r'^$', ArticleListView.as_view(), name='article-list'),
-        )
+        ]
 
     **Example myapp/article_list.html**:
 

+ 3 - 3
docs/ref/class-based-views/index.txt

@@ -25,9 +25,9 @@ a thread-safe operation).
 A class-based view is deployed into a URL pattern using the
 :meth:`~django.views.generic.base.View.as_view()` classmethod::
 
-    urlpatterns = patterns('',
-        (r'^view/$', MyView.as_view(size=42)),
-    )
+    urlpatterns = [
+        url(r'^view/$', MyView.as_view(size=42)),
+    ]
 
 .. admonition:: Thread safety with view arguments
 

+ 19 - 19
docs/ref/contrib/admin/index.txt

@@ -1395,9 +1395,9 @@ templates used by the :class:`ModelAdmin` views:
         class MyModelAdmin(admin.ModelAdmin):
             def get_urls(self):
                 urls = super(MyModelAdmin, self).get_urls()
-                my_urls = patterns('',
-                    (r'^my_view/$', self.my_view)
-                )
+                my_urls = [
+                    url(r'^my_view/$', self.my_view),
+                ]
                 return my_urls + urls
 
             def my_view(self, request):
@@ -1432,9 +1432,9 @@ templates used by the :class:`ModelAdmin` views:
         class MyModelAdmin(admin.ModelAdmin):
             def get_urls(self):
                 urls = super(MyModelAdmin, self).get_urls()
-                my_urls = patterns('',
-                    (r'^my_view/$', self.admin_site.admin_view(self.my_view))
-                )
+                my_urls = [
+                    url(r'^my_view/$', self.admin_site.admin_view(self.my_view))
+                ]
                 return my_urls + urls
 
     Notice the wrapped view in the fifth line above::
@@ -2434,23 +2434,23 @@ In this example, we register the default ``AdminSite`` instance
 ``django.contrib.admin.site`` at the URL ``/admin/`` ::
 
     # urls.py
-    from django.conf.urls import patterns, include
+    from django.conf.urls import include, url
     from django.contrib import admin
 
-    urlpatterns = patterns('',
-        (r'^admin/', include(admin.site.urls)),
-    )
+    urlpatterns = [
+        url(r'^admin/', include(admin.site.urls)),
+    ]
 
 In this example, we register the ``AdminSite`` instance
 ``myproject.admin.admin_site`` at the URL ``/myadmin/`` ::
 
     # urls.py
-    from django.conf.urls import patterns, include
+    from django.conf.urls import include, url
     from myproject.admin import admin_site
 
-    urlpatterns = patterns('',
-        (r'^myadmin/', include(admin_site.urls)),
-    )
+    urlpatterns = [
+        url(r'^myadmin/', include(admin_site.urls)),
+    ]
 
 Note that you may not want autodiscovery of ``admin`` modules when using your
 own ``AdminSite`` instance since you will likely be importing all the per-app
@@ -2472,13 +2472,13 @@ separate versions of the admin site -- using the ``AdminSite`` instances
 respectively::
 
     # urls.py
-    from django.conf.urls import patterns, include
+    from django.conf.urls import include, url
     from myproject.admin import basic_site, advanced_site
 
-    urlpatterns = patterns('',
-        (r'^basic-admin/', include(basic_site.urls)),
-        (r'^advanced-admin/', include(advanced_site.urls)),
-    )
+    urlpatterns = [
+        url(r'^basic-admin/', include(basic_site.urls)),
+        url(r'^advanced-admin/', include(advanced_site.urls)),
+    ]
 
 ``AdminSite`` instances take a single argument to their constructor, their
 name, which can be anything you like. This argument becomes the prefix to the

+ 17 - 13
docs/ref/contrib/flatpages.txt

@@ -46,9 +46,9 @@ Then either:
 
 3. Add an entry in your URLconf. For example::
 
-    urlpatterns = patterns('',
-        (r'^pages/', include('django.contrib.flatpages.urls')),
-    )
+    urlpatterns = [
+        url(r'^pages/', include('django.contrib.flatpages.urls')),
+    ]
 
 or:
 
@@ -73,17 +73,19 @@ Using the URLconf
 There are several ways to include the flat pages in your URLconf. You can
 dedicate a particular path to flat pages::
 
-    urlpatterns = patterns('',
-        (r'^pages/', include('django.contrib.flatpages.urls')),
-    )
+    urlpatterns = [
+        url(r'^pages/', include('django.contrib.flatpages.urls')),
+    ]
 
 You can also set it up as a "catchall" pattern. In this case, it is important
 to place the pattern at the end of the other urlpatterns::
 
+    from django.contrib.flatpages import views
+
     # Your other patterns here
-    urlpatterns += patterns('django.contrib.flatpages.views',
-        (r'^(?P<url>.*/)$', 'flatpage'),
-    )
+    urlpatterns += [
+        url(r'^(?P<url>.*/)$', views.flatpage),
+    ]
 
 .. warning::
 
@@ -95,10 +97,12 @@ Another common setup is to use flat pages for a limited set of known pages and
 to hard code the urls, so you can reference them with the :ttag:`url` template
 tag::
 
-    urlpatterns += patterns('django.contrib.flatpages.views',
-        url(r'^about-us/$', 'flatpage', {'url': '/about-us/'}, name='about'),
-        url(r'^license/$', 'flatpage', {'url': '/license/'}, name='license'),
-    )
+    from django.contrib.flatpages import views
+
+    urlpatterns += [
+        url(r'^about-us/$', views.flatpage, {'url': '/about-us/'}, name='about'),
+        url(r'^license/$', views.flatpage, {'url': '/license/'}, name='license'),
+    ]
 
 Using the middleware
 --------------------

+ 14 - 14
docs/ref/contrib/formtools/form-wizard.txt

@@ -251,14 +251,14 @@ deploy the new :class:`WizardView` object at a URL in the ``urls.py``. The
 wizard's ``as_view()`` method takes a list of your
 :class:`~django.forms.Form` classes as an argument during instantiation::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
 
     from myapp.forms import ContactForm1, ContactForm2
     from myapp.views import ContactWizard
 
-    urlpatterns = patterns('',
-        (r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
-    )
+    urlpatterns = [
+        url(r'^contact/$', ContactWizard.as_view([ContactForm1, ContactForm2])),
+    ]
 
 You can also pass the form list as a class attribute named ``form_list``::
 
@@ -311,9 +311,9 @@ Here's what the view code might look like::
 
 The ``urls.py`` file would contain something like::
 
-    urlpatterns = patterns('',
-        (r'^checkout/$', OrderWizard.as_view(FORMS, condition_dict={'cc': pay_by_credit_card})),
-    )
+    urlpatterns = [
+        url(r'^checkout/$', OrderWizard.as_view(FORMS, condition_dict={'cc': pay_by_credit_card})),
+    ]
 
 The ``condition_dict`` can be passed as attribute for the ``as_view()`
 method or as a class attribute named ``condition_dict``::
@@ -673,18 +673,18 @@ We define our wizard in a ``views.py``::
 
 We need to add the ``ContactWizard`` to our ``urls.py`` file::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
 
     from myapp.forms import ContactForm1, ContactForm2
     from myapp.views import ContactWizard, show_message_form_condition
 
     contact_forms = [ContactForm1, ContactForm2]
 
-    urlpatterns = patterns('',
-        (r'^contact/$', ContactWizard.as_view(contact_forms,
+    urlpatterns = [
+        url(r'^contact/$', ContactWizard.as_view(contact_forms,
             condition_dict={'1': show_message_form_condition}
         )),
-    )
+    ]
 
 As you can see, we defined a ``show_message_form_condition`` next to our
 :class:`WizardView` subclass and added a ``condition_dict`` argument to the
@@ -728,7 +728,7 @@ Additionally you have to pass two more arguments to the
 
 Example code for the changed ``urls.py`` file::
 
-    from django.conf.urls import url, patterns
+    from django.conf.urls import url
 
     from myapp.forms import ContactForm1, ContactForm2
     from myapp.views import ContactWizard
@@ -741,10 +741,10 @@ Example code for the changed ``urls.py`` file::
     contact_wizard = ContactWizard.as_view(named_contact_forms,
         url_name='contact_step', done_step_name='finished')
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^contact/(?P<step>.+)/$', contact_wizard, name='contact_step'),
         url(r'^contact/$', contact_wizard, name='contact'),
-    )
+    ]
 
 Advanced ``NamedUrlWizardView`` methods
 =======================================

+ 3 - 3
docs/ref/contrib/gis/tutorial.txt

@@ -730,12 +730,12 @@ Let's dive right in.  Create a file called ``admin.py`` inside the
 
 Next, edit your ``urls.py`` in the ``geodjango`` application folder as follows::
 
-    from django.conf.urls import patterns, url, include
+    from django.conf.urls import url, include
     from django.contrib.gis import admin
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^admin/', include(admin.site.urls)),
-    )
+    ]
 
 Start up the Django development server:
 

+ 21 - 17
docs/ref/contrib/sitemaps.txt

@@ -265,7 +265,7 @@ Example
 
 Here's an example of a :doc:`URLconf </topics/http/urls>` using both::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from django.contrib.sitemaps import FlatPageSitemap, GenericSitemap
     from blog.models import Entry
 
@@ -279,13 +279,13 @@ Here's an example of a :doc:`URLconf </topics/http/urls>` using both::
         'blog': GenericSitemap(info_dict, priority=0.6),
     }
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # some generic view using info_dict
         # ...
 
         # the sitemap
-        (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
-    )
+        url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
+    ]
 
 .. _URLconf: ../url_dispatch/
 
@@ -313,20 +313,20 @@ the sitemap. For example::
             return reverse(item)
 
     # urls.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from .sitemaps import StaticViewSitemap
 
     sitemaps = {
         'static': StaticViewSitemap,
     }
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^$', 'views.main', name='main'),
         url(r'^about/$', 'views.about', name='about'),
         url(r'^license/$', 'views.license', name='license'),
         # ...
         url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
-    )
+    ]
 
 
 Creating a sitemap index
@@ -345,10 +345,12 @@ references individual sitemap files, one per each section defined in your
 
 Here's what the relevant URLconf lines would look like for the example above::
 
-    urlpatterns = patterns('django.contrib.sitemaps.views',
-        (r'^sitemap\.xml$', 'index', {'sitemaps': sitemaps}),
-        (r'^sitemap-(?P<section>.+)\.xml$', 'sitemap', {'sitemaps': sitemaps}),
-    )
+    from django.contrib.sitemaps import views
+
+    urlpatterns = [
+        url(r'^sitemap\.xml$', views.index, {'sitemaps': sitemaps}),
+        url(r'^sitemap-(?P<section>.+)\.xml$', views.sitemap, {'sitemaps': sitemaps}),
+    ]
 
 This will automatically generate a :file:`sitemap.xml` file that references
 both :file:`sitemap-flatpages.xml` and :file:`sitemap-blog.xml`. The
@@ -366,14 +368,14 @@ with a caching decorator -- you must name your sitemap view and pass
     from django.contrib.sitemaps import views as sitemaps_views
     from django.views.decorators.cache import cache_page
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^sitemap\.xml$',
             cache_page(86400)(sitemaps_views.index),
             {'sitemaps': sitemaps, 'sitemap_url_name': 'sitemaps'}),
         url(r'^sitemap-(?P<section>.+)\.xml$',
             cache_page(86400)(sitemaps_views.sitemap),
             {'sitemaps': sitemaps}, name='sitemaps'),
-    )
+    ]
 
 
 Template customization
@@ -383,16 +385,18 @@ If you wish to use a different template for each sitemap or sitemap index
 available on your site, you may specify it by passing a ``template_name``
 parameter to the ``sitemap`` and ``index`` views via the URLconf::
 
-    urlpatterns = patterns('django.contrib.sitemaps.views',
-        (r'^custom-sitemap\.xml$', 'index', {
+    from django.contrib.sitemaps import views
+
+    urlpatterns = [
+        url(r'^custom-sitemap\.xml$', views.index, {
             'sitemaps': sitemaps,
             'template_name': 'custom_sitemap.html'
         }),
-        (r'^custom-sitemap-(?P<section>.+)\.xml$', 'sitemap', {
+        url(r'^custom-sitemap-(?P<section>.+)\.xml$', views.sitemap, {
             'sitemaps': sitemaps,
             'template_name': 'custom_sitemap.html'
         }),
-    )
+    ]
 
 
 These views return :class:`~django.template.response.TemplateResponse`

+ 4 - 3
docs/ref/contrib/staticfiles.txt

@@ -445,11 +445,12 @@ local development server, add the following snippet to the end of your
 primary URL configuration::
 
    from django.conf import settings
+   from django.contrib.staticfiles import views
 
    if settings.DEBUG:
-       urlpatterns += patterns('django.contrib.staticfiles.views',
-           url(r'^static/(?P<path>.*)$', 'serve'),
-       )
+       urlpatterns += [
+           url(r'^static/(?P<path>.*)$', views.serve),
+       ]
 
 Note, the beginning of the pattern (``r'^static/'``) should be your
 :setting:`STATIC_URL` setting.

+ 9 - 9
docs/ref/contrib/syndication.txt

@@ -77,14 +77,14 @@ a feed of the latest five news items::
 To connect a URL to this feed, put an instance of the Feed object in
 your :doc:`URLconf </topics/http/urls>`. For example::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from myproject.feeds import LatestEntriesFeed
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ...
-        (r'^latest/feed/$', LatestEntriesFeed()),
+        url(r'^latest/feed/$', LatestEntriesFeed()),
         # ...
-    )
+    ]
 
 Note:
 
@@ -366,15 +366,15 @@ Here's a full example::
 
 And the accompanying URLconf::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from myproject.feeds import RssSiteNewsFeed, AtomSiteNewsFeed
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ...
-        (r'^sitenews/rss/$', RssSiteNewsFeed()),
-        (r'^sitenews/atom/$', AtomSiteNewsFeed()),
+        url(r'^sitenews/rss/$', RssSiteNewsFeed()),
+        url(r'^sitenews/atom/$', AtomSiteNewsFeed()),
         # ...
-    )
+    ]
 
 Feed class reference
 --------------------

+ 39 - 10
docs/ref/urls.txt

@@ -9,11 +9,42 @@ patterns()
 
 .. function:: patterns(prefix, pattern_description, ...)
 
+.. deprecated:: 1.8
+
+    ``urlpatterns`` should be a plain list of :func:`django.conf.urls.url`
+    instances instead.
+
 A function that takes a prefix, and an arbitrary number of URL patterns, and
 returns a list of URL patterns in the format Django needs.
 
-The first argument to ``patterns()`` is a string ``prefix``. See
-:ref:`The view prefix <urlpatterns-view-prefix>`.
+The first argument to ``patterns()`` is a string ``prefix``. Here's the example
+URLconf from the :doc:`Django overview </intro/overview>`::
+
+    from django.conf.urls import patterns, url
+
+    urlpatterns = patterns('',
+        url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
+    )
+
+In this example, each view has a common prefix -- ``'news.views'``.
+Instead of typing that out for each entry in ``urlpatterns``, you can use the
+first argument to the ``patterns()`` function to specify a prefix to apply to
+each view function.
+
+With this in mind, the above example can be written more concisely as::
+
+    from django.conf.urls import patterns, url
+
+    urlpatterns = patterns('news.views',
+        url(r'^articles/(\d{4})/$', 'year_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
+        url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
+    )
+
+Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
+that in automatically.
 
 The remaining arguments should be tuples in this format::
 
@@ -54,23 +85,21 @@ Helper function to return a URL pattern for serving files in debug mode::
     from django.conf import settings
     from django.conf.urls.static import static
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ... the rest of your URLconf goes here ...
-    ) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
 
 url()
 -----
 
 .. function:: url(regex, view, kwargs=None, name=None, prefix='')
 
-You can use the ``url()`` function, instead of a tuple, as an argument to
-``patterns()``. This is convenient if you want to specify a name without the
-optional extra arguments dictionary. For example::
+``urlpatterns`` should be a list of ``url()`` instances. For example::
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^index/$', index_view, name="main-view"),
         ...
-    )
+    ]
 
 This function takes five arguments, most of which are optional::
 
@@ -107,7 +136,7 @@ include()
     :type namespace: string
     :arg app_name: Application namespace for the URL entries being included
     :type app_name: string
-    :arg pattern_list: Iterable of URL entries as returned by :func:`patterns`
+    :arg pattern_list: Iterable of :func:`django.conf.urls.url` instances
     :arg app_namespace: Application namespace for the URL entries being included
     :type app_namespace: string
     :arg instance_namespace: Instance namespace for the URL entries being included

+ 4 - 3
docs/ref/views.txt

@@ -26,15 +26,16 @@ built-in handling for user-uploaded files, but you can have Django serve your
 :setting:`MEDIA_ROOT` by appending something like this to your URLconf::
 
     from django.conf import settings
+    from django.views.static import serve
 
     # ... the rest of your URLconf goes here ...
 
     if settings.DEBUG:
-        urlpatterns += patterns('',
-            url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
+        urlpatterns += [
+            url(r'^media/(?P<path>.*)$', serve, {
                 'document_root': settings.MEDIA_ROOT,
             }),
-       )
+       ]
 
 Note, the snippet assumes your :setting:`MEDIA_URL` has a value of
 ``'/media/'``. This will call the :func:`~django.views.static.serve` view,

+ 59 - 0
docs/releases/1.8.txt

@@ -203,3 +203,62 @@ Django 1.6 introduced ``{% load cycle from future %}`` and
 :ttag:`cycle` and :ttag:`firstof` template tags. This syntax is now deprecated
 and will be removed in Django 2.0. You can simply remove the
 ``{% load ... from future %}`` tags.
+
+``django.conf.urls.patterns()``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In the olden days of Django, it was encouraged to reference views as strings
+in ``urlpatterns``::
+
+    urlpatterns = patterns('',
+        url('^$', 'myapp.views.myview'),
+    )
+
+and Django would magically import ``myapp.views.myview`` internally and turn
+the string into a real function reference. In order to reduce repetition when
+referencing many views from the same module, the ``patterns()`` function takes
+a required initial ``prefix`` argument which is prepended to all
+views-as-strings in that set of ``urlpatterns``::
+
+    urlpatterns = patterns('myapp.views',
+        url('^$', 'myview'),
+        url('^other/$', 'otherview'),
+    )
+
+In the modern era, we have updated the tutorial to instead recommend importing
+your views module and referencing your view functions (or classes) directly.
+This has a number of advantages, all deriving from the fact that we are using
+normal Python in place of "Django String Magic": the errors when you mistype a
+view name are less obscure, IDEs can help with autocompletion of view names,
+etc.
+
+So these days, the above use of the ``prefix`` arg is much more likely to be
+written (and is better written) as::
+
+    from myapp import views
+
+    urlpatterns = patterns('',
+        url('^$', views.myview),
+        url('^other/$', views.otherview),
+    )
+
+Thus ``patterns()`` serves little purpose and is a burden when teaching new users
+(answering the newbie's question "why do I need this empty string as the first
+argument to ``patterns()``?"). For these reasons, we are deprecating it.
+Updating your code is as simple as ensuring that ``urlpatterns`` is a string of
+:func:`django.conf.urls.url` instances. For example::
+
+    from django.conf.urls import url
+    from myapp import views
+
+    urlpatterns = [
+        url('^$', views.myview),
+        url('^other/$', views.otherview),
+    ]
+
+``prefix`` argument to :func:`~django.conf.urls.i18n.i18n_patterns`
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Related to the previous item, the ``prefix`` argument to
+:func:`django.conf.urls.i18n.i18n_patterns` has been deprecated. Simply pass a
+list of :func:`django.conf.urls.url` instances instead.

+ 1 - 0
docs/spelling_wordlist

@@ -23,6 +23,7 @@ attr
 auth
 autoclobber
 autocommit
+autocompletion
 autoconf
 autodetect
 autodetectable

+ 9 - 9
docs/topics/cache.txt

@@ -532,9 +532,9 @@ The per-view cache, like the per-site cache, is keyed off of the URL. If
 multiple URLs point at the same view, each URL will be cached separately.
 Continuing the ``my_view`` example, if your URLconf looks like this::
 
-    urlpatterns = ('',
-        (r'^foo/(\d{1,2})/$', my_view),
-    )
+    urlpatterns = [
+        url(r'^foo/(\d{1,2})/$', my_view),
+    ]
 
 then requests to ``/foo/1/`` and ``/foo/23/`` will be cached separately, as
 you may expect. But once a particular URL (e.g., ``/foo/23/``) has been
@@ -578,17 +578,17 @@ themselves.
 Doing so is easy: simply wrap the view function with ``cache_page`` when you
 refer to it in the URLconf. Here's the old URLconf from earlier::
 
-    urlpatterns = ('',
-        (r'^foo/(\d{1,2})/$', my_view),
-    )
+    urlpatterns = [
+        url(r'^foo/(\d{1,2})/$', my_view),
+    ]
 
 Here's the same thing, with ``my_view`` wrapped in ``cache_page``::
 
     from django.views.decorators.cache import cache_page
 
-    urlpatterns = ('',
-        (r'^foo/(\d{1,2})/$', cache_page(60 * 15)(my_view)),
-    )
+    urlpatterns = [
+        url(r'^foo/(\d{1,2})/$', cache_page(60 * 15)(my_view)),
+    ]
 
 .. templatetag:: cache
 

+ 10 - 10
docs/topics/class-based-views/generic-display.txt

@@ -119,12 +119,12 @@ Now we need to define a view::
 Finally hook that view into your urls::
 
     # urls.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from books.views import PublisherList
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^publishers/$', PublisherList.as_view()),
-    )
+    ]
 
 That's all the Python code we need to write. We still need to write a template,
 however. We could explicitly tell the view which template to use by adding a
@@ -330,12 +330,12 @@ various useful things are stored on ``self``; as well as the request
 Here, we have a URLconf with a single captured group::
 
     # urls.py
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from books.views import PublisherBookList
 
-    urlpatterns = patterns('',
-        (r'^books/([\w-]+)/$', PublisherBookList.as_view()),
-    )
+    urlpatterns = [
+        url(r'^books/([\w-]+)/$', PublisherBookList.as_view()),
+    ]
 
 Next, we'll write the ``PublisherBookList`` view itself::
 
@@ -396,13 +396,13 @@ updated.
 First, we'd need to add an author detail bit in the URLconf to point to a
 custom view::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from books.views import AuthorDetailView
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         #...
         url(r'^authors/(?P<pk>\d+)/$', AuthorDetailView.as_view(), name='author-detail'),
-    )
+    ]
 
 Then we'd write our new view -- ``get_object`` is the method that retrieves the
 object -- so we simply override it and wrap the call::

+ 3 - 3
docs/topics/class-based-views/generic-editing.txt

@@ -141,15 +141,15 @@ an :exc:`~django.core.exceptions.ImproperlyConfigured` exception if it's not.
 Finally, we hook these new views into the URLconf::
 
     # urls.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from myapp.views import AuthorCreate, AuthorUpdate, AuthorDelete
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ...
         url(r'author/add/$', AuthorCreate.as_view(), name='author_add'),
         url(r'author/(?P<pk>\d+)/$', AuthorUpdate.as_view(), name='author_update'),
         url(r'author/(?P<pk>\d+)/delete/$', AuthorDelete.as_view(), name='author_delete'),
-    )
+    ]
 
 .. note::
 

+ 12 - 12
docs/topics/class-based-views/index.txt

@@ -38,12 +38,12 @@ URLconf. If you're only changing a few simple attributes on a class-based view,
 you can simply pass them into the
 :meth:`~django.views.generic.base.View.as_view` method call itself::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from django.views.generic import TemplateView
 
-    urlpatterns = patterns('',
-        (r'^about/', TemplateView.as_view(template_name="about.html")),
-    )
+    urlpatterns = [
+        url(r'^about/', TemplateView.as_view(template_name="about.html")),
+    ]
 
 Any arguments passed to :meth:`~django.views.generic.base.View.as_view` will
 override attributes set on the class. In this example, we set ``template_name``
@@ -75,12 +75,12 @@ class method instead, which provides a function-like entry to class-based
 views::
 
     # urls.py
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from some_app.views import AboutView
 
-    urlpatterns = patterns('',
-        (r'^about/', AboutView.as_view()),
-    )
+    urlpatterns = [
+        url(r'^about/', AboutView.as_view()),
+    ]
 
 
 For more information on how to use the built in generic views, consult the next
@@ -100,12 +100,12 @@ preferable to ask the API when the most recent book was published.
 
 We map the URL to book list view in the URLconf::
 
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from books.views import BookListView
 
-    urlpatterns = patterns('',
-        (r'^books/$', BookListView.as_view()),
-    )
+    urlpatterns = [
+        url(r'^books/$', BookListView.as_view()),
+    ]
 
 And the view::
 

+ 11 - 11
docs/topics/class-based-views/intro.txt

@@ -89,12 +89,12 @@ request to a matching method if one is defined, or raises
 :class:`~django.http.HttpResponseNotAllowed` if not::
 
     # urls.py
-    from django.conf.urls import patterns
+    from django.conf.urls import url
     from myapp.views import MyView
 
-    urlpatterns = patterns('',
-        (r'^about/', MyView.as_view()),
-    )
+    urlpatterns = [
+        url(r'^about/', MyView.as_view()),
+    ]
 
 
 It is worth noting that what your method returns is identical to what you
@@ -129,9 +129,9 @@ You can override that in a subclass::
 Another option is to configure class attributes as keyword arguments to the
 :meth:`~django.views.generic.base.View.as_view` call in the URLconf::
 
-    urlpatterns = patterns('',
-        (r'^about/', GreetingView.as_view(greeting="G'day")),
-    )
+    urlpatterns = [
+        url(r'^about/', GreetingView.as_view(greeting="G'day")),
+    ]
 
 .. note::
 
@@ -268,10 +268,10 @@ The easiest place to do this is in the URLconf where you deploy your view::
 
     from .views import VoteView
 
-    urlpatterns = patterns('',
-        (r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
-        (r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
-    )
+    urlpatterns = [
+        url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))),
+        url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())),
+    ]
 
 This approach applies the decorator on a per-instance basis. If you
 want every instance of a view to be decorated, you need to take a

+ 3 - 3
docs/topics/class-based-views/mixins.txt

@@ -256,13 +256,13 @@ mixin.
 We can hook this into our URLs easily enough::
 
     # urls.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from books.views import RecordInterest
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         #...
         url(r'^author/(?P<pk>\d+)/interest/$', RecordInterest.as_view(), name='author-interest'),
-    )
+    ]
 
 Note the ``pk`` named group, which
 :meth:`~django.views.generic.detail.SingleObjectMixin.get_object` uses

+ 99 - 163
docs/topics/http/urls.txt

@@ -45,8 +45,8 @@ algorithm the system follows to determine which Python code to execute:
    will be used in place of the :setting:`ROOT_URLCONF` setting.
 
 2. Django loads that Python module and looks for the variable
-   ``urlpatterns``. This should be a Python list, in the format returned by
-   the function :func:`django.conf.urls.patterns`.
+   ``urlpatterns``. This should be a Python list of :func:`django.conf.urls.url`
+   instances.
 
 3. Django runs through each URL pattern, in order, and stops at the first
    one that matches the requested URL.
@@ -72,14 +72,14 @@ Example
 
 Here's a sample URLconf::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^articles/2003/$', 'news.views.special_case_2003'),
         url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
         url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
         url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
-    )
+    ]
 
 Notes:
 
@@ -129,14 +129,14 @@ is ``(?P<name>pattern)``, where ``name`` is the name of the group and
 
 Here's the above example URLconf, rewritten to use named groups::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^articles/2003/$', 'news.views.special_case_2003'),
         url(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
         url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
         url(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/$', 'news.views.article_detail'),
-    )
+    ]
 
 This accomplishes exactly the same thing as the previous example, with one
 subtle difference: The captured values are passed to view functions as keyword
@@ -203,12 +203,12 @@ A convenient trick is to specify default parameters for your views' arguments.
 Here's an example URLconf and view::
 
     # URLconf
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^blog/$', 'blog.views.page'),
         url(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
-    )
+    ]
 
     # View (in blog/views.py)
     def page(request, num="1"):
@@ -230,9 +230,8 @@ accessed. This makes the system blazingly fast.
 Syntax of the urlpatterns variable
 ==================================
 
-``urlpatterns`` should be a Python list, in the format returned by the function
-:func:`django.conf.urls.patterns`. Always use ``patterns()`` to create
-the ``urlpatterns`` variable.
+``urlpatterns`` should be a Python list of :func:`~django.conf.urls.url`
+instances.
 
 Error handling
 ==============
@@ -260,73 +259,6 @@ The variables are:
 * ``handler403`` -- See :data:`django.conf.urls.handler403`.
 * ``handler400`` -- See :data:`django.conf.urls.handler400`.
 
-.. _urlpatterns-view-prefix:
-
-The view prefix
-===============
-
-You can specify a common prefix in your ``patterns()`` call, to cut down on
-code duplication.
-
-Here's the example URLconf from the :doc:`Django overview </intro/overview>`::
-
-    from django.conf.urls import patterns, url
-
-    urlpatterns = patterns('',
-        url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
-        url(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
-        url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
-    )
-
-In this example, each view has a common prefix -- ``'news.views'``.
-Instead of typing that out for each entry in ``urlpatterns``, you can use the
-first argument to the ``patterns()`` function to specify a prefix to apply to
-each view function.
-
-With this in mind, the above example can be written more concisely as::
-
-    from django.conf.urls import patterns, url
-
-    urlpatterns = patterns('news.views',
-        url(r'^articles/(\d{4})/$', 'year_archive'),
-        url(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
-        url(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
-    )
-
-Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
-that in automatically.
-
-Multiple view prefixes
-----------------------
-
-In practice, you'll probably end up mixing and matching views to the point
-where the views in your ``urlpatterns`` won't have a common prefix. However,
-you can still take advantage of the view prefix shortcut to remove duplication.
-Just add multiple ``patterns()`` objects together, like this:
-
-Old::
-
-    from django.conf.urls import patterns, url
-
-    urlpatterns = patterns('',
-        url(r'^$', 'myapp.views.app_index'),
-        url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'myapp.views.month_display'),
-        url(r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'),
-    )
-
-New::
-
-    from django.conf.urls import patterns, url
-
-    urlpatterns = patterns('myapp.views',
-        url(r'^$', 'app_index'),
-        url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','month_display'),
-    )
-
-    urlpatterns += patterns('weblog.views',
-        url(r'^tag/(?P<tag>\w+)/$', 'tag'),
-    )
-
 .. _including-other-urlconfs:
 
 Including other URLconfs
@@ -338,14 +270,14 @@ essentially "roots" a set of URLs below other ones.
 For example, here's an excerpt of the URLconf for the `Django Web site`_
 itself. It includes a number of other URLconfs::
 
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         # ... snip ...
         url(r'^community/', include('django_website.aggregator.urls')),
         url(r'^contact/', include('django_website.contact.urls')),
         # ... snip ...
-    )
+    ]
 
 Note that the regular expressions in this example don't have a ``$``
 (end-of-string match character) but do include a trailing slash. Whenever
@@ -353,23 +285,21 @@ Django encounters ``include()`` (:func:`django.conf.urls.include()`), it chops
 off whatever part of the URL matched up to that point and sends the remaining
 string to the included URLconf for further processing.
 
-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 :func:`~django.conf.urls.patterns`
-instead. For example, consider this URLconf::
+Another possibility is to include additional URL patterns by using a list of
+:func:`~django.conf.urls.url` instances. For example, consider this URLconf::
 
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
 
-    extra_patterns = patterns('',
+    extra_patterns = [
         url(r'^reports/(?P<id>\d+)/$', 'credit.views.report'),
         url(r'^charge/$', 'credit.views.charge'),
-    )
+    ]
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^$', 'apps.main.views.homepage'),
         url(r'^help/', include('apps.help.urls')),
         url(r'^credit/', include(extra_patterns)),
-    )
+    ]
 
 In this example, the ``/credit/reports/`` URL will be handled by the
 ``credit.views.report()`` Django view.
@@ -377,28 +307,30 @@ In this example, the ``/credit/reports/`` URL will be handled by the
 This can be used to remove redundancy from URLconfs where a single pattern
 prefix is used repeatedly. For example, consider this URLconf::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
+    from . import views
 
-    urlpatterns = patterns('wiki.views',
-        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/history/$', 'history'),
-        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/edit/$', 'edit'),
-        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/discuss/$', 'discuss'),
-        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/permissions/$', 'permissions'),
-    )
+    urlpatterns = [
+        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/history/$', views.history),
+        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/edit/$', views.edit),
+        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/discuss/$', views.discuss),
+        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/permissions/$', views.permissions),
+    ]
 
 We can improve this by stating the common path prefix only once and grouping
 the suffixes that differ::
 
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
+    from . import views
 
-    urlpatterns = patterns('',
-        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/', include(patterns('wiki.views',
-            url(r'^history/$', 'history'),
-            url(r'^edit/$', 'edit'),
-            url(r'^discuss/$', 'discuss'),
-            url(r'^permissions/$', 'permissions'),
-        ))),
-    )
+    urlpatterns = [
+        url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/', include([
+            url(r'^history/$', views.history),
+            url(r'^edit/$', views.edit),
+            url(r'^discuss/$', views.discuss),
+            url(r'^permissions/$', views.permissions),
+        ])),
+    ]
 
 .. _`Django Web site`: https://www.djangoproject.com/
 
@@ -409,19 +341,20 @@ An included URLconf receives any captured parameters from parent URLconfs, so
 the following example is valid::
 
     # In settings/urls/main.py
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
-    )
+    ]
 
     # In foo/urls/blog.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
+    from . import views
 
-    urlpatterns = patterns('foo.views',
-        url(r'^$', 'blog.index'),
-        url(r'^archive/$', 'blog.archive'),
-    )
+    urlpatterns = [
+        url(r'^$', views.blog.index),
+        url(r'^archive/$', views.blog.archive),
+    ]
 
 In the above example, the captured ``"username"`` variable is passed to the
 included URLconf, as expected.
@@ -440,11 +373,12 @@ function.
 
 For example::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
+    from . import views
 
-    urlpatterns = patterns('blog.views',
-        url(r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),
-    )
+    urlpatterns = [
+        url(r'^blog/(?P<year>\d{4})/$', views.year_archive, {'foo': 'bar'}),
+    ]
 
 In this example, for a request to ``/blog/2005/``, Django will call
 ``blog.views.year_archive(request, year='2005', foo='bar')``.
@@ -472,36 +406,38 @@ For example, these two URLconf sets are functionally identical:
 Set one::
 
     # main.py
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^blog/', include('inner'), {'blogid': 3}),
-    )
+    ]
 
     # inner.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
+    from mysite import views
 
-    urlpatterns = patterns('',
-        url(r'^archive/$', 'mysite.views.archive'),
-        url(r'^about/$', 'mysite.views.about'),
-    )
+    urlpatterns = [
+        url(r'^archive/$', views.archive),
+        url(r'^about/$', views.about),
+    ]
 
 Set two::
 
     # main.py
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
+    from mysite import views
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^blog/', include('inner')),
-    )
+    ]
 
     # inner.py
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
-        url(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
-        url(r'^about/$', 'mysite.views.about', {'blogid': 3}),
-    )
+    urlpatterns = [
+        url(r'^archive/$', views.archive, {'blogid': 3}),
+        url(r'^about/$', views.about, {'blogid': 3}),
+    ]
 
 Note that extra options will *always* be passed to *every* line in the included
 URLconf, regardless of whether the line's view actually accepts those options
@@ -517,38 +453,38 @@ supported -- you can pass any callable object as the view.
 
 For example, given this URLconf in "string" notation::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^archive/$', 'mysite.views.archive'),
         url(r'^about/$', 'mysite.views.about'),
         url(r'^contact/$', 'mysite.views.contact'),
-    )
+    ]
 
 You can accomplish the same thing by passing objects rather than strings. Just
 be sure to import the objects::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from mysite.views import archive, about, contact
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^archive/$', archive),
         url(r'^about/$', about),
         url(r'^contact/$', contact),
-    )
+    ]
 
 The following example is functionally identical. It's just a bit more compact
 because it imports the module that contains the views, rather than importing
 each view individually::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from mysite import views
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^archive/$', views.archive),
         url(r'^about/$', views.about),
         url(r'^contact/$', views.contact),
-    )
+    ]
 
 The style you use is up to you.
 
@@ -558,12 +494,12 @@ the view prefix (as explained in "The view prefix" above) will have no effect.
 Note that :doc:`class based views</topics/class-based-views/index>` must be
 imported::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from mysite.views import ClassBasedView
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^myview/$', ClassBasedView.as_view()),
-    )
+    ]
 
 Reverse resolution of URLs
 ==========================
@@ -618,13 +554,13 @@ Examples
 
 Consider again this URLconf entry::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         #...
         url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
         #...
-    )
+    ]
 
 According to this design, the URL for the archive corresponding to year *nnnn*
 is ``/articles/nnnn/``.
@@ -670,13 +606,13 @@ It's fairly common to use the same view function in multiple URL patterns in
 your URLconf. For example, these two URL patterns both point to the ``archive``
 view::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from mysite.views import archive
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^archive/(\d{4})/$', archive),
         url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}),
-    )
+    ]
 
 This is completely valid, but it leads to problems when you try to do reverse
 URL matching (through the :func:`~django.core.urlresolvers.reverse` function
@@ -691,13 +627,13 @@ matching.
 
 Here's the above example, rewritten to use named URL patterns::
 
-    from django.conf.urls import patterns, url
+    from django.conf.urls import url
     from mysite.views import archive
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^archive/(\d{4})/$', archive, name="full-archive"),
         url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, name="arch-summary"),
-    )
+    ]
 
 With these names in place (``full-archive`` and ``arch-summary``), you can
 target each pattern individually by using its name:
@@ -859,20 +795,20 @@ This will include the URLs defined in ``apps.help.urls`` into the
 ``'foo'``.
 
 Secondly, you can include an object that contains embedded namespace data. If
-you ``include()`` an object as returned by :func:`~django.conf.urls.patterns`,
+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::
 
-    (<patterns object>, <application namespace>, <instance namespace>)
+    (<list of url() instances>, <application namespace>, <instance namespace>)
 
 For example::
 
-    from django.conf.urls import include, patterns, url
+    from django.conf.urls import include, url
 
-    help_patterns = patterns('',
+    help_patterns = [
         url(r'^basic/$', 'apps.help.views.views.basic'),
         url(r'^advanced/$', 'apps.help.views.views.advanced'),
-    )
+    ]
 
     url(r'^help/', include((help_patterns, 'bar', 'foo'))),
 

+ 27 - 20
docs/topics/i18n/translation.txt

@@ -911,13 +911,15 @@ URL. Paths listed in :setting:`LOCALE_PATHS` are also included.
 
 You hook it up like this::
 
+    from django.views.i18n import javascript_catalog
+
     js_info_dict = {
         'packages': ('your.app.package',),
     }
 
-    urlpatterns = patterns('',
-        (r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
-    )
+    urlpatterns = [
+        url(r'^jsi18n/$', javascript_catalog, js_info_dict),
+    ]
 
 Each string in ``packages`` should be in Python dotted-package syntax (the
 same format as the strings in :setting:`INSTALLED_APPS`) and should refer to a
@@ -935,9 +937,9 @@ changed by altering the ``domain`` argument.
 
 You can make the view dynamic by putting the packages into the URL pattern::
 
-    urlpatterns = patterns('',
-        (r'^jsi18n/(?P<packages>\S+?)/$', 'django.views.i18n.javascript_catalog'),
-    )
+    urlpatterns = [
+        url(r'^jsi18n/(?P<packages>\S+?)/$', javascript_catalog),
+    ]
 
 With this, you specify the packages as a list of package names delimited by '+'
 signs in the URL. This is especially useful if your pages use code from
@@ -1085,25 +1087,30 @@ Language prefix in URL patterns
 
 .. function:: i18n_patterns(prefix, pattern_description, ...)
 
-This function can be used in your root URLconf as a replacement for the normal
-:func:`django.conf.urls.patterns` function. Django will automatically
+.. deprecated:: 1.8
+
+    The ``prefix`` argument to ``i18n_patterns()`` has been deprecated and will
+    not be supported in Django 2.0. Simply pass a list of
+    :func:`django.conf.urls.url` instances instead.
+
+This function can be used in your root URLconf and Django will automatically
 prepend the current active language code to all url patterns defined within
 :func:`~django.conf.urls.i18n.i18n_patterns`. Example URL patterns::
 
-    from django.conf.urls import patterns, include, url
+    from django.conf.urls import include, url
     from django.conf.urls.i18n import i18n_patterns
 
-    urlpatterns = patterns('',
+    urlpatterns = [
         url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'),
-    )
+    ]
 
-    news_patterns = patterns('',
+    news_patterns = [
         url(r'^$', 'news.views.index', name='index'),
         url(r'^category/(?P<slug>[\w-]+)/$', 'news.views.category', name='category'),
         url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'),
-    )
+    ]
 
-    urlpatterns += i18n_patterns('',
+    urlpatterns += i18n_patterns(
         url(r'^about/$', 'about.view', name='about'),
         url(r'^news/', include(news_patterns, namespace='news')),
     )
@@ -1144,21 +1151,21 @@ Translating URL patterns
 URL patterns can also be marked translatable using the
 :func:`~django.utils.translation.ugettext_lazy` function. Example::
 
-    from django.conf.urls import patterns, include, url
+    from django.conf.urls import include, url
     from django.conf.urls.i18n import i18n_patterns
     from django.utils.translation import ugettext_lazy as _
 
-    urlpatterns = patterns(''
+    urlpatterns = [
         url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'),
-    )
+    ]
 
-    news_patterns = patterns(''
+    news_patterns = [
         url(r'^$', 'news.views.index', name='index'),
         url(_(r'^category/(?P<slug>[\w-]+)/$'), 'news.views.category', name='category'),
         url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'),
-    )
+    ]
 
-    urlpatterns += i18n_patterns('',
+    urlpatterns += i18n_patterns(
         url(_(r'^about/$'), 'about.view', name='about'),
         url(_(r'^news/'), include(news_patterns, namespace='news')),
     )

+ 4 - 4
tests/admin_changelist/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from . import admin
 
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 3 - 3
tests/admin_custom_urls/models.py

@@ -35,7 +35,7 @@ class ActionAdmin(admin.ModelAdmin):
     def get_urls(self):
         # Add the URL of our custom 'add_view' view to the front of the URLs
         # list.  Remove the existing one(s) first
-        from django.conf.urls import patterns, url
+        from django.conf.urls import url
 
         def wrap(view):
             def wrapper(*args, **kwargs):
@@ -46,9 +46,9 @@ class ActionAdmin(admin.ModelAdmin):
 
         view_name = '%s_%s_add' % info
 
-        return patterns('',
+        return [
             url(r'^!add/$', wrap(self.add_view), name=view_name),
-        ) + self.remove_url(view_name)
+        ] + self.remove_url(view_name)
 
 
 class Person(models.Model):

+ 4 - 4
tests/admin_custom_urls/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 from django.contrib import admin
 
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 10 - 10
tests/admin_docs/urls.py

@@ -1,16 +1,16 @@
-from django.conf.urls import include, patterns, url
+from django.conf.urls import include, url
 from django.contrib import admin
 
 from . import views
 
-ns_patterns = patterns('',
+ns_patterns = [
     url(r'^xview/func/$', views.xview_dec(views.xview), name='func'),
-)
+]
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-    (r'^admindocs/', include('django.contrib.admindocs.urls')),
-    (r'^', include(ns_patterns, namespace='test')),
-    (r'^xview/func/$', views.xview_dec(views.xview)),
-    (r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+    url(r'^admindocs/', include('django.contrib.admindocs.urls')),
+    url(r'^', include(ns_patterns, namespace='test')),
+    url(r'^xview/func/$', views.xview_dec(views.xview)),
+    url(r'^xview/class/$', views.xview_dec(views.XViewClass.as_view())),
+]

+ 4 - 4
tests/admin_inlines/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from . import admin
 
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 5 - 6
tests/admin_scripts/urls.py

@@ -1,11 +1,10 @@
 import os
-from django.conf.urls import patterns
+from django.conf.urls import url
 from django.utils._os import upath
 
 here = os.path.dirname(upath(__file__))
 
-urlpatterns = patterns('',
-    (r'^custom_templates/(?P<path>.*)$', 'django.views.static.serve', {
-        'document_root': os.path.join(here, 'custom_templates'),
-    }),
-)
+urlpatterns = [
+    url(r'^custom_templates/(?P<path>.*)$', 'django.views.static.serve', {
+        'document_root': os.path.join(here, 'custom_templates')}),
+]

+ 3 - 3
tests/admin_views/admin.py

@@ -11,7 +11,7 @@ from django.core.exceptions import ValidationError
 from django.core.files.storage import FileSystemStorage
 from django.core.mail import EmailMessage
 from django.core.servers.basehttp import FileWrapper
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.forms.models import BaseModelFormSet
 from django.http import HttpResponse, StreamingHttpResponse
 from django.contrib.admin import BooleanFieldListFilter
@@ -617,11 +617,11 @@ class ReportAdmin(admin.ModelAdmin):
 
     def get_urls(self):
         # Corner case: Don't call parent implementation
-        return patterns('',
+        return [
             url(r'^extra/$',
                 self.extra,
                 name='cable_extra'),
-        )
+        ]
 
 
 class CustomTemplateBooleanFieldListFilter(BooleanFieldListFilter):

+ 4 - 4
tests/admin_views/customadmin.py

@@ -3,7 +3,7 @@ A second, custom AdminSite -- see tests.CustomAdminSiteTests.
 """
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns
+from django.conf.urls import url
 from django.contrib import admin
 from django.http import HttpResponse
 from django.contrib.auth.models import User
@@ -26,9 +26,9 @@ class Admin2(admin.AdminSite):
         return super(Admin2, self).index(request, {'foo': '*bar*'})
 
     def get_urls(self):
-        return patterns('',
-            (r'^my_view/$', self.admin_view(self.my_view)),
-        ) + super(Admin2, self).get_urls()
+        return [
+            url(r'^my_view/$', self.admin_view(self.my_view)),
+        ] + super(Admin2, self).get_urls()
 
     def my_view(self, request):
         return HttpResponse("Django is a magical pony!")

+ 10 - 10
tests/admin_views/urls.py

@@ -1,14 +1,14 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from . import views, customadmin, admin
 
 
-urlpatterns = patterns('',
-    (r'^test_admin/admin/doc/', include('django.contrib.admindocs.urls')),
-    (r'^test_admin/admin/secure-view/$', views.secure_view),
-    (r'^test_admin/admin/', include(admin.site.urls)),
-    (r'^test_admin/admin2/', include(customadmin.site.urls)),
-    (r'^test_admin/admin3/', include(admin.site.urls), dict(form_url='pony')),
-    (r'^test_admin/admin4/', include(customadmin.simple_site.urls)),
-    (r'^test_admin/admin5/', include(admin.site2.urls)),
-)
+urlpatterns = [
+    url(r'^test_admin/admin/doc/', include('django.contrib.admindocs.urls')),
+    url(r'^test_admin/admin/secure-view/$', views.secure_view),
+    url(r'^test_admin/admin/', include(admin.site.urls)),
+    url(r'^test_admin/admin2/', include(customadmin.site.urls)),
+    url(r'^test_admin/admin3/', include(admin.site.urls), dict(form_url='pony')),
+    url(r'^test_admin/admin4/', include(customadmin.simple_site.urls)),
+    url(r'^test_admin/admin5/', include(admin.site2.urls)),
+]

+ 4 - 4
tests/admin_widgets/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from . import widgetadmin
 
 
-urlpatterns = patterns('',
-    (r'^', include(widgetadmin.site.urls)),
-)
+urlpatterns = [
+    url(r'^', include(widgetadmin.site.urls)),
+]

+ 8 - 8
tests/conditional_processing/urls.py

@@ -1,12 +1,12 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
-    ('^condition/$', views.index),
-    ('^condition/last_modified/$', views.last_modified_view1),
-    ('^condition/last_modified2/$', views.last_modified_view2),
-    ('^condition/etag/$', views.etag_view1),
-    ('^condition/etag2/$', views.etag_view2),
-)
+urlpatterns = [
+    url('^condition/$', views.index),
+    url('^condition/last_modified/$', views.last_modified_view1),
+    url('^condition/last_modified2/$', views.last_modified_view2),
+    url('^condition/etag/$', views.etag_view1),
+    url('^condition/etag2/$', views.etag_view2),
+]

+ 5 - 4
tests/contenttypes_tests/urls.py

@@ -1,7 +1,8 @@
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns
+from django.conf.urls import url
+from django.contrib.contenttypes import views
 
-urlpatterns = patterns('',
-    (r'^shortcut/(\d+)/(.*)/$', 'django.contrib.contenttypes.views.shortcut'),
-)
+urlpatterns = [
+    url(r'^shortcut/(\d+)/(.*)/$', views.shortcut),
+]

+ 4 - 4
tests/context_processors/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
-    (r'^request_attrs/$', views.request_processor),
-)
+urlpatterns = [
+    url(r'^request_attrs/$', views.request_processor),
+]

+ 3 - 3
tests/file_storage/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.http import HttpResponse
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^$', lambda req: HttpResponse('example view')),
-)
+]

+ 14 - 14
tests/file_uploads/urls.py

@@ -1,18 +1,18 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
-    (r'^upload/$', views.file_upload_view),
-    (r'^verify/$', views.file_upload_view_verify),
-    (r'^unicode_name/$', views.file_upload_unicode_name),
-    (r'^echo/$', views.file_upload_echo),
-    (r'^echo_content_type_extra/$', views.file_upload_content_type_extra),
-    (r'^echo_content/$', views.file_upload_echo_content),
-    (r'^quota/$', views.file_upload_quota),
-    (r'^quota/broken/$', views.file_upload_quota_broken),
-    (r'^getlist_count/$', views.file_upload_getlist_count),
-    (r'^upload_errors/$', views.file_upload_errors),
-    (r'^filename_case/$', views.file_upload_filename_case_view),
-)
+urlpatterns = [
+    url(r'^upload/$', views.file_upload_view),
+    url(r'^verify/$', views.file_upload_view_verify),
+    url(r'^unicode_name/$', views.file_upload_unicode_name),
+    url(r'^echo/$', views.file_upload_echo),
+    url(r'^echo_content_type_extra/$', views.file_upload_content_type_extra),
+    url(r'^echo_content/$', views.file_upload_echo_content),
+    url(r'^quota/$', views.file_upload_quota),
+    url(r'^quota/broken/$', views.file_upload_quota_broken),
+    url(r'^getlist_count/$', views.file_upload_getlist_count),
+    url(r'^upload_errors/$', views.file_upload_errors),
+    url(r'^filename_case/$', views.file_upload_filename_case_view),
+]

+ 3 - 3
tests/forms_tests/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from .views import ArticleFormView
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^model_form/(?P<pk>\d+)/$', ArticleFormView.as_view(), name="article_form"),
-)
+]

+ 4 - 4
tests/generic_inline_admin/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from . import admin
 
-urlpatterns = patterns('',
-    (r'^generic_inline_admin/admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^generic_inline_admin/admin/', include(admin.site.urls)),
+]

+ 107 - 111
tests/generic_views/urls.py

@@ -1,4 +1,4 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.views.decorators.cache import cache_page
 from django.views.generic import TemplateView
 
@@ -6,26 +6,22 @@ from . import models
 from . import views
 
 
-urlpatterns = patterns('',
-    # base
-    #(r'^about/login-required/$',
-    #    views.DecoratedAboutView()),
-
+urlpatterns = [
     # TemplateView
-    (r'^template/no_template/$',
+    url(r'^template/no_template/$',
         TemplateView.as_view()),
-    (r'^template/simple/(?P<foo>\w+)/$',
+    url(r'^template/simple/(?P<foo>\w+)/$',
         TemplateView.as_view(template_name='generic_views/about.html')),
-    (r'^template/custom/(?P<foo>\w+)/$',
+    url(r'^template/custom/(?P<foo>\w+)/$',
         views.CustomTemplateView.as_view(template_name='generic_views/about.html')),
-    (r'^template/content_type/$',
+    url(r'^template/content_type/$',
         TemplateView.as_view(template_name='generic_views/robots.txt', content_type='text/plain')),
 
-    (r'^template/cached/(?P<foo>\w+)/$',
+    url(r'^template/cached/(?P<foo>\w+)/$',
         cache_page(2.0)(TemplateView.as_view(template_name='generic_views/about.html'))),
 
     # DetailView
-    (r'^detail/obj/$',
+    url(r'^detail/obj/$',
         views.ObjectDetail.as_view()),
     url(r'^detail/artist/(?P<pk>\d+)/$',
         views.ArtistDetail.as_view(),
@@ -33,102 +29,102 @@ urlpatterns = patterns('',
     url(r'^detail/author/(?P<pk>\d+)/$',
         views.AuthorDetail.as_view(),
         name="author_detail"),
-    (r'^detail/author/bycustompk/(?P<foo>\d+)/$',
+    url(r'^detail/author/bycustompk/(?P<foo>\d+)/$',
         views.AuthorDetail.as_view(pk_url_kwarg='foo')),
-    (r'^detail/author/byslug/(?P<slug>[\w-]+)/$',
+    url(r'^detail/author/byslug/(?P<slug>[\w-]+)/$',
         views.AuthorDetail.as_view()),
-    (r'^detail/author/bycustomslug/(?P<foo>[\w-]+)/$',
+    url(r'^detail/author/bycustomslug/(?P<foo>[\w-]+)/$',
         views.AuthorDetail.as_view(slug_url_kwarg='foo')),
-    (r'^detail/author/(?P<pk>\d+)/template_name_suffix/$',
+    url(r'^detail/author/(?P<pk>\d+)/template_name_suffix/$',
         views.AuthorDetail.as_view(template_name_suffix='_view')),
-    (r'^detail/author/(?P<pk>\d+)/template_name/$',
+    url(r'^detail/author/(?P<pk>\d+)/template_name/$',
         views.AuthorDetail.as_view(template_name='generic_views/about.html')),
-    (r'^detail/author/(?P<pk>\d+)/context_object_name/$',
+    url(r'^detail/author/(?P<pk>\d+)/context_object_name/$',
         views.AuthorDetail.as_view(context_object_name='thingy')),
-    (r'^detail/author/(?P<pk>\d+)/dupe_context_object_name/$',
+    url(r'^detail/author/(?P<pk>\d+)/dupe_context_object_name/$',
         views.AuthorDetail.as_view(context_object_name='object')),
-    (r'^detail/page/(?P<pk>\d+)/field/$',
+    url(r'^detail/page/(?P<pk>\d+)/field/$',
         views.PageDetail.as_view()),
-    (r'^detail/author/invalid/url/$',
+    url(r'^detail/author/invalid/url/$',
         views.AuthorDetail.as_view()),
-    (r'^detail/author/invalid/qs/$',
+    url(r'^detail/author/invalid/qs/$',
         views.AuthorDetail.as_view(queryset=None)),
-    (r'^detail/nonmodel/1/$',
+    url(r'^detail/nonmodel/1/$',
         views.NonModelDetail.as_view()),
-    (r'^detail/doesnotexist/(?P<pk>\d+)/$',
+    url(r'^detail/doesnotexist/(?P<pk>\d+)/$',
         views.ObjectDoesNotExistDetail.as_view()),
     # FormView
-    (r'^contact/$',
+    url(r'^contact/$',
         views.ContactView.as_view()),
 
     # Create/UpdateView
-    (r'^edit/artists/create/$',
+    url(r'^edit/artists/create/$',
         views.ArtistCreate.as_view()),
-    (r'^edit/artists/(?P<pk>\d+)/update/$',
+    url(r'^edit/artists/(?P<pk>\d+)/update/$',
         views.ArtistUpdate.as_view()),
 
-    (r'^edit/authors/create/naive/$',
+    url(r'^edit/authors/create/naive/$',
         views.NaiveAuthorCreate.as_view()),
-    (r'^edit/authors/create/redirect/$',
+    url(r'^edit/authors/create/redirect/$',
         views.NaiveAuthorCreate.as_view(success_url='/edit/authors/create/')),
-    (r'^edit/authors/create/interpolate_redirect/$',
+    url(r'^edit/authors/create/interpolate_redirect/$',
         views.NaiveAuthorCreate.as_view(success_url='/edit/author/%(id)d/update/')),
-    (r'^edit/authors/create/restricted/$',
+    url(r'^edit/authors/create/restricted/$',
         views.AuthorCreateRestricted.as_view()),
-    (r'^edit/authors/create/$',
+    url(r'^edit/authors/create/$',
         views.AuthorCreate.as_view()),
-    (r'^edit/authors/create/special/$',
+    url(r'^edit/authors/create/special/$',
         views.SpecializedAuthorCreate.as_view()),
 
-    (r'^edit/author/(?P<pk>\d+)/update/naive/$',
+    url(r'^edit/author/(?P<pk>\d+)/update/naive/$',
         views.NaiveAuthorUpdate.as_view()),
-    (r'^edit/author/(?P<pk>\d+)/update/redirect/$',
+    url(r'^edit/author/(?P<pk>\d+)/update/redirect/$',
         views.NaiveAuthorUpdate.as_view(success_url='/edit/authors/create/')),
-    (r'^edit/author/(?P<pk>\d+)/update/interpolate_redirect/$',
+    url(r'^edit/author/(?P<pk>\d+)/update/interpolate_redirect/$',
         views.NaiveAuthorUpdate.as_view(success_url='/edit/author/%(id)d/update/')),
-    (r'^edit/author/(?P<pk>\d+)/update/$',
+    url(r'^edit/author/(?P<pk>\d+)/update/$',
         views.AuthorUpdate.as_view()),
-    (r'^edit/author/update/$',
+    url(r'^edit/author/update/$',
         views.OneAuthorUpdate.as_view()),
-    (r'^edit/author/(?P<pk>\d+)/update/special/$',
+    url(r'^edit/author/(?P<pk>\d+)/update/special/$',
         views.SpecializedAuthorUpdate.as_view()),
-    (r'^edit/author/(?P<pk>\d+)/delete/naive/$',
+    url(r'^edit/author/(?P<pk>\d+)/delete/naive/$',
         views.NaiveAuthorDelete.as_view()),
-    (r'^edit/author/(?P<pk>\d+)/delete/redirect/$',
+    url(r'^edit/author/(?P<pk>\d+)/delete/redirect/$',
         views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/')),
-    (r'^edit/author/(?P<pk>\d+)/delete/interpolate_redirect/$',
+    url(r'^edit/author/(?P<pk>\d+)/delete/interpolate_redirect/$',
         views.NaiveAuthorDelete.as_view(success_url='/edit/authors/create/?deleted=%(id)s')),
-    (r'^edit/author/(?P<pk>\d+)/delete/$',
+    url(r'^edit/author/(?P<pk>\d+)/delete/$',
         views.AuthorDelete.as_view()),
-    (r'^edit/author/(?P<pk>\d+)/delete/special/$',
+    url(r'^edit/author/(?P<pk>\d+)/delete/special/$',
         views.SpecializedAuthorDelete.as_view()),
 
     # ArchiveIndexView
-    (r'^dates/books/$',
+    url(r'^dates/books/$',
         views.BookArchive.as_view()),
-    (r'^dates/books/context_object_name/$',
+    url(r'^dates/books/context_object_name/$',
         views.BookArchive.as_view(context_object_name='thingies')),
-    (r'^dates/books/allow_empty/$',
+    url(r'^dates/books/allow_empty/$',
         views.BookArchive.as_view(allow_empty=True)),
-    (r'^dates/books/template_name/$',
+    url(r'^dates/books/template_name/$',
         views.BookArchive.as_view(template_name='generic_views/list.html')),
-    (r'^dates/books/template_name_suffix/$',
+    url(r'^dates/books/template_name_suffix/$',
         views.BookArchive.as_view(template_name_suffix='_detail')),
-    (r'^dates/books/invalid/$',
+    url(r'^dates/books/invalid/$',
         views.BookArchive.as_view(queryset=None)),
-    (r'^dates/books/paginated/$',
+    url(r'^dates/books/paginated/$',
         views.BookArchive.as_view(paginate_by=10)),
-    (r'^dates/books/reverse/$',
+    url(r'^dates/books/reverse/$',
         views.BookArchive.as_view(queryset=models.Book.objects.order_by('pubdate'))),
-    (r'^dates/books/by_month/$',
+    url(r'^dates/books/by_month/$',
         views.BookArchive.as_view(date_list_period='month')),
-    (r'^dates/booksignings/$',
+    url(r'^dates/booksignings/$',
         views.BookSigningArchive.as_view()),
 
     # ListView
-    (r'^list/dict/$',
+    url(r'^list/dict/$',
         views.DictList.as_view()),
-    (r'^list/dict/paginated/$',
+    url(r'^list/dict/paginated/$',
         views.DictList.as_view(paginate_by=1)),
     url(r'^list/artists/$',
         views.ArtistList.as_view(),
@@ -136,130 +132,130 @@ urlpatterns = patterns('',
     url(r'^list/authors/$',
         views.AuthorList.as_view(),
         name="authors_list"),
-    (r'^list/authors/paginated/$',
+    url(r'^list/authors/paginated/$',
         views.AuthorList.as_view(paginate_by=30)),
-    (r'^list/authors/paginated/(?P<page>\d+)/$',
+    url(r'^list/authors/paginated/(?P<page>\d+)/$',
         views.AuthorList.as_view(paginate_by=30)),
-    (r'^list/authors/paginated-orphaned/$',
+    url(r'^list/authors/paginated-orphaned/$',
         views.AuthorList.as_view(paginate_by=30, paginate_orphans=2)),
-    (r'^list/authors/notempty/$',
+    url(r'^list/authors/notempty/$',
         views.AuthorList.as_view(allow_empty=False)),
-    (r'^list/authors/notempty/paginated/$',
+    url(r'^list/authors/notempty/paginated/$',
         views.AuthorList.as_view(allow_empty=False, paginate_by=2)),
-    (r'^list/authors/template_name/$',
+    url(r'^list/authors/template_name/$',
         views.AuthorList.as_view(template_name='generic_views/list.html')),
-    (r'^list/authors/template_name_suffix/$',
+    url(r'^list/authors/template_name_suffix/$',
         views.AuthorList.as_view(template_name_suffix='_objects')),
-    (r'^list/authors/context_object_name/$',
+    url(r'^list/authors/context_object_name/$',
         views.AuthorList.as_view(context_object_name='author_list')),
-    (r'^list/authors/dupe_context_object_name/$',
+    url(r'^list/authors/dupe_context_object_name/$',
         views.AuthorList.as_view(context_object_name='object_list')),
-    (r'^list/authors/invalid/$',
+    url(r'^list/authors/invalid/$',
         views.AuthorList.as_view(queryset=None)),
-    (r'^list/authors/paginated/custom_class/$',
+    url(r'^list/authors/paginated/custom_class/$',
         views.AuthorList.as_view(paginate_by=5, paginator_class=views.CustomPaginator)),
-    (r'^list/authors/paginated/custom_page_kwarg/$',
+    url(r'^list/authors/paginated/custom_page_kwarg/$',
         views.AuthorList.as_view(paginate_by=30, page_kwarg='pagina')),
-    (r'^list/authors/paginated/custom_constructor/$',
+    url(r'^list/authors/paginated/custom_constructor/$',
         views.AuthorListCustomPaginator.as_view()),
 
     # YearArchiveView
     # Mixing keyword and positional captures below is intentional; the views
     # ought to be able to accept either.
-    (r'^dates/books/(?P<year>\d{4})/$',
+    url(r'^dates/books/(?P<year>\d{4})/$',
         views.BookYearArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/make_object_list/$',
+    url(r'^dates/books/(?P<year>\d{4})/make_object_list/$',
         views.BookYearArchive.as_view(make_object_list=True)),
-    (r'^dates/books/(?P<year>\d{4})/allow_empty/$',
+    url(r'^dates/books/(?P<year>\d{4})/allow_empty/$',
         views.BookYearArchive.as_view(allow_empty=True)),
-    (r'^dates/books/(?P<year>\d{4})/allow_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/allow_future/$',
         views.BookYearArchive.as_view(allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/paginated/$',
+    url(r'^dates/books/(?P<year>\d{4})/paginated/$',
         views.BookYearArchive.as_view(make_object_list=True, paginate_by=30)),
-    (r'^dates/books/no_year/$',
+    url(r'^dates/books/no_year/$',
         views.BookYearArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/reverse/$',
+    url(r'^dates/books/(?P<year>\d{4})/reverse/$',
         views.BookYearArchive.as_view(queryset=models.Book.objects.order_by('pubdate'))),
-    (r'^dates/booksignings/(?P<year>\d{4})/$',
+    url(r'^dates/booksignings/(?P<year>\d{4})/$',
         views.BookSigningYearArchive.as_view()),
 
     # MonthArchiveView
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
         views.BookMonthArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/$',
         views.BookMonthArchive.as_view(month_format='%m')),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_empty/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_empty/$',
         views.BookMonthArchive.as_view(allow_empty=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/allow_future/$',
         views.BookMonthArchive.as_view(allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/paginated/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/paginated/$',
         views.BookMonthArchive.as_view(paginate_by=30)),
-    (r'^dates/books/(?P<year>\d{4})/no_month/$',
+    url(r'^dates/books/(?P<year>\d{4})/no_month/$',
         views.BookMonthArchive.as_view()),
-    (r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
+    url(r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/$',
         views.BookSigningMonthArchive.as_view()),
 
     # WeekArchiveView
-    (r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$',
         views.BookWeekArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_empty/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_empty/$',
         views.BookWeekArchive.as_view(allow_empty=True)),
-    (r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/allow_future/$',
         views.BookWeekArchive.as_view(allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/paginated/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/paginated/$',
         views.BookWeekArchive.as_view(paginate_by=30)),
-    (r'^dates/books/(?P<year>\d{4})/week/no_week/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/no_week/$',
         views.BookWeekArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/monday/$',
+    url(r'^dates/books/(?P<year>\d{4})/week/(?P<week>\d{1,2})/monday/$',
         views.BookWeekArchive.as_view(week_format='%W')),
-    (r'^dates/booksignings/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$',
+    url(r'^dates/booksignings/(?P<year>\d{4})/week/(?P<week>\d{1,2})/$',
         views.BookSigningWeekArchive.as_view()),
 
     # DayArchiveView
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
         views.BookDayArchive.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$',
         views.BookDayArchive.as_view(month_format='%m')),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty/$',
         views.BookDayArchive.as_view(allow_empty=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_future/$',
         views.BookDayArchive.as_view(allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty_and_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/allow_empty_and_future/$',
         views.BookDayArchive.as_view(allow_empty=True, allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/paginated/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/paginated/$',
         views.BookDayArchive.as_view(paginate_by=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/no_day/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/no_day/$',
         views.BookDayArchive.as_view()),
-    (r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
+    url(r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
         views.BookSigningDayArchive.as_view()),
 
     # TodayArchiveView
-    (r'^dates/books/today/$',
+    url(r'^dates/books/today/$',
         views.BookTodayArchive.as_view()),
-    (r'^dates/books/today/allow_empty/$',
+    url(r'^dates/books/today/allow_empty/$',
         views.BookTodayArchive.as_view(allow_empty=True)),
-    (r'^dates/booksignings/today/$',
+    url(r'^dates/booksignings/today/$',
         views.BookSigningTodayArchive.as_view()),
 
     # DateDetailView
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
         views.BookDetail.as_view()),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
         views.BookDetail.as_view(month_format='%m')),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/allow_future/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/allow_future/$',
         views.BookDetail.as_view(allow_future=True)),
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/nopk/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/nopk/$',
         views.BookDetail.as_view()),
 
-    (r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/byslug/(?P<slug>[\w-]+)/$',
+    url(r'^dates/books/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/byslug/(?P<slug>[\w-]+)/$',
         views.BookDetail.as_view()),
 
-    (r'^dates/books/get_object_custom_queryset/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
+    url(r'^dates/books/get_object_custom_queryset/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
         views.BookDetailGetObjectCustomQueryset.as_view()),
 
-    (r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
+    url(r'^dates/booksignings/(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/(?P<pk>\d+)/$',
         views.BookSigningDetail.as_view()),
 
     # Useful for testing redirects
-    (r'^accounts/login/$', 'django.contrib.auth.views.login')
-)
+    url(r'^accounts/login/$', 'django.contrib.auth.views.login')
+]

+ 3 - 3
tests/handlers/urls.py

@@ -1,13 +1,13 @@
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from . import views
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^regular/$', views.regular),
     url(r'^streaming/$', views.streaming),
     url(r'^in_transaction/$', views.in_transaction),
     url(r'^not_in_transaction/$', views.not_in_transaction),
     url(r'^suspicious/$', views.suspicious),
-)
+]

+ 4 - 4
tests/i18n/patterns/urls/default.py

@@ -1,4 +1,4 @@
-from django.conf.urls import patterns, include, url
+from django.conf.urls import include, url
 from django.conf.urls.i18n import i18n_patterns
 from django.utils.translation import ugettext_lazy as _
 from django.views.generic import TemplateView
@@ -6,14 +6,14 @@ from django.views.generic import TemplateView
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^not-prefixed/$', view, name='not-prefixed'),
     url(r'^not-prefixed-include/', include('i18n.patterns.urls.included')),
     url(_(r'^translated/$'), view, name='no-prefix-translated'),
     url(_(r'^translated/(?P<slug>[\w-]+)/$'), view, name='no-prefix-translated-slug'),
-)
+]
 
-urlpatterns += i18n_patterns('',
+urlpatterns += i18n_patterns(
     url(r'^prefixed/$', view, name='prefixed'),
     url(r'^prefixed\.xml$', view, name='prefixed_xml'),
     url(_(r'^users/$'), view, name='users'),

+ 1 - 1
tests/i18n/patterns/urls/disabled.py

@@ -4,6 +4,6 @@ from django.views.generic import TemplateView
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = i18n_patterns('',
+urlpatterns = i18n_patterns(
     url(r'^prefixed/$', view, name='prefixed'),
 )

+ 3 - 3
tests/i18n/patterns/urls/included.py

@@ -1,9 +1,9 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.views.generic import TemplateView
 
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^foo/$', view, name='not-prefixed-included-url'),
-)
+]

+ 3 - 3
tests/i18n/patterns/urls/namespace.py

@@ -1,11 +1,11 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.utils.translation import ugettext_lazy as _
 from django.views.generic import TemplateView
 
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(_(r'^register/$'), view, name='register'),
     url(_(r'^register-without-slash$'), view, name='register-without-slash'),
-)
+]

+ 2 - 3
tests/i18n/patterns/urls/path_unused.py

@@ -1,10 +1,9 @@
 from django.conf.urls import url
-from django.conf.urls import patterns
 from django.views.generic import TemplateView
 
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^nl/foo/', view, name='not-translated'),
-)
+]

+ 1 - 1
tests/i18n/patterns/urls/wrong.py

@@ -3,6 +3,6 @@ from django.conf.urls.i18n import i18n_patterns
 from django.utils.translation import ugettext_lazy as _
 
 
-urlpatterns = i18n_patterns('',
+urlpatterns = i18n_patterns(
     url(_(r'^account/'), include('i18n.patterns.urls.wrong_namespace', namespace='account')),
 )

+ 1 - 1
tests/i18n/patterns/urls/wrong_namespace.py

@@ -6,6 +6,6 @@ from django.views.generic import TemplateView
 
 view = TemplateView.as_view(template_name='dummy.html')
 
-urlpatterns = i18n_patterns('',
+urlpatterns = i18n_patterns(
     url(_(r'^register/$'), view, name='register'),
 )

+ 11 - 4
tests/i18n/urls.py

@@ -1,10 +1,17 @@
 from __future__ import unicode_literals
+import warnings
 
 from django.conf.urls.i18n import i18n_patterns
 from django.http import HttpResponse, StreamingHttpResponse
 from django.utils.translation import ugettext_lazy as _
 
-urlpatterns = i18n_patterns('',
-    (r'^simple/$', lambda r: HttpResponse()),
-    (r'^streaming/$', lambda r: StreamingHttpResponse([_("Yes"), "/", _("No")])),
-)
+
+# test deprecated version of i18_patterns() function (with prefix). Remove it
+# and convert to list of urls() in Django 2.0
+with warnings.catch_warnings(record=True):
+    warnings.filterwarnings('ignore', module='django.conf.urls.18n')
+
+    urlpatterns = i18n_patterns('',
+        (r'^simple/$', lambda r: HttpResponse()),
+        (r'^streaming/$', lambda r: StreamingHttpResponse([_("Yes"), "/", _("No")])),
+    )

+ 3 - 3
tests/logging_tests/urls.py

@@ -1,10 +1,10 @@
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from . import views
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^suspicious/$', views.suspicious),
     url(r'^suspicious_spec/$', views.suspicious_spec),
-)
+]

+ 4 - 4
tests/middleware/cond_get_urls.py

@@ -1,6 +1,6 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 from django.http import HttpResponse
 
-urlpatterns = patterns('',
-    (r'^$', lambda request: HttpResponse('root is here')),
-)
+urlpatterns = [
+    url(r'^$', lambda request: HttpResponse('root is here')),
+]

+ 6 - 6
tests/middleware/extra_urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
-urlpatterns = patterns('',
-    (r'^customurlconf/noslash$', 'view'),
-    (r'^customurlconf/slash/$', 'view'),
-    (r'^customurlconf/needsquoting#/$', 'view'),
-)
+urlpatterns = [
+    url(r'^customurlconf/noslash$', 'view'),
+    url(r'^customurlconf/slash/$', 'view'),
+    url(r'^customurlconf/needsquoting#/$', 'view'),
+]

+ 6 - 6
tests/middleware/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
-urlpatterns = patterns('',
-    (r'^noslash$', 'view'),
-    (r'^slash/$', 'view'),
-    (r'^needsquoting#/$', 'view'),
-)
+urlpatterns = [
+    url(r'^noslash$', 'view'),
+    url(r'^slash/$', 'view'),
+    url(r'^needsquoting#/$', 'view'),
+]

+ 10 - 10
tests/middleware_exceptions/urls.py

@@ -1,14 +1,14 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import views
 
-urlpatterns = patterns('',
-    (r'^middleware_exceptions/view/$', views.normal_view),
-    (r'^middleware_exceptions/not_found/$', views.not_found),
-    (r'^middleware_exceptions/error/$', views.server_error),
-    (r'^middleware_exceptions/null_view/$', views.null_view),
-    (r'^middleware_exceptions/permission_denied/$', views.permission_denied),
+urlpatterns = [
+    url(r'^middleware_exceptions/view/$', views.normal_view),
+    url(r'^middleware_exceptions/not_found/$', views.not_found),
+    url(r'^middleware_exceptions/error/$', views.server_error),
+    url(r'^middleware_exceptions/null_view/$', views.null_view),
+    url(r'^middleware_exceptions/permission_denied/$', views.permission_denied),
 
-    (r'^middleware_exceptions/template_response/$', views.template_response),
-    (r'^middleware_exceptions/template_response_error/$', views.template_response_error),
-)
+    url(r'^middleware_exceptions/template_response/$', views.template_response),
+    url(r'^middleware_exceptions/template_response_error/$', views.template_response_error),
+]

+ 3 - 3
tests/model_permalink/urls.py

@@ -1,5 +1,5 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^guitarists/(\w{1,50})/$', 'unimplemented_view_placeholder', name='guitarist_detail'),
-)
+]

+ 4 - 4
tests/proxy_models/urls.py

@@ -1,7 +1,7 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 
 from django.contrib import admin
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 5 - 5
tests/resolve_url/urls.py

@@ -1,6 +1,6 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
+from django.contrib.auth import views
 
-
-urlpatterns = patterns('',
-    (r'^accounts/logout/$', 'django.contrib.auth.views.logout')
-)
+urlpatterns = [
+    url(r'^accounts/logout/$', views.logout),
+]

+ 3 - 3
tests/servers/urls.py

@@ -1,11 +1,11 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^example_view/$', views.example_view),
     url(r'^model_view/$', views.model_view),
     url(r'^create_model_instance/$', views.create_model_instance),
     url(r'^environ_view/$', views.environ_view),
-)
+]

+ 5 - 4
tests/staticfiles_tests/urls/default.py

@@ -1,5 +1,6 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
+from django.contrib.staticfiles import views
 
-urlpatterns = patterns('',
-    url(r'^static/(?P<path>.*)$', 'django.contrib.staticfiles.views.serve'),
-)
+urlpatterns = [
+    url(r'^static/(?P<path>.*)$', views.serve),
+]

+ 18 - 18
tests/syndication_tests/urls.py

@@ -1,24 +1,24 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import feeds
 
 
-urlpatterns = patterns('django.contrib.syndication.views',
-    (r'^syndication/complex/(?P<foo>.*)/$', feeds.ComplexFeed()),
-    (r'^syndication/rss2/$', feeds.TestRss2Feed()),
-    (r'^syndication/rss2/guid_ispermalink_true/$',
+urlpatterns = [
+    url(r'^syndication/complex/(?P<foo>.*)/$', feeds.ComplexFeed()),
+    url(r'^syndication/rss2/$', feeds.TestRss2Feed()),
+    url(r'^syndication/rss2/guid_ispermalink_true/$',
         feeds.TestRss2FeedWithGuidIsPermaLinkTrue()),
-    (r'^syndication/rss2/guid_ispermalink_false/$',
+    url(r'^syndication/rss2/guid_ispermalink_false/$',
         feeds.TestRss2FeedWithGuidIsPermaLinkFalse()),
-    (r'^syndication/rss091/$', feeds.TestRss091Feed()),
-    (r'^syndication/no_pubdate/$', feeds.TestNoPubdateFeed()),
-    (r'^syndication/atom/$', feeds.TestAtomFeed()),
-    (r'^syndication/latest/$', feeds.TestLatestFeed()),
-    (r'^syndication/custom/$', feeds.TestCustomFeed()),
-    (r'^syndication/naive-dates/$', feeds.NaiveDatesFeed()),
-    (r'^syndication/aware-dates/$', feeds.TZAwareDatesFeed()),
-    (r'^syndication/feedurl/$', feeds.TestFeedUrlFeed()),
-    (r'^syndication/articles/$', feeds.ArticlesFeed()),
-    (r'^syndication/template/$', feeds.TemplateFeed()),
-    (r'^syndication/template_context/$', feeds.TemplateContextFeed()),
-)
+    url(r'^syndication/rss091/$', feeds.TestRss091Feed()),
+    url(r'^syndication/no_pubdate/$', feeds.TestNoPubdateFeed()),
+    url(r'^syndication/atom/$', feeds.TestAtomFeed()),
+    url(r'^syndication/latest/$', feeds.TestLatestFeed()),
+    url(r'^syndication/custom/$', feeds.TestCustomFeed()),
+    url(r'^syndication/naive-dates/$', feeds.NaiveDatesFeed()),
+    url(r'^syndication/aware-dates/$', feeds.TZAwareDatesFeed()),
+    url(r'^syndication/feedurl/$', feeds.TestFeedUrlFeed()),
+    url(r'^syndication/articles/$', feeds.ArticlesFeed()),
+    url(r'^syndication/template/$', feeds.TemplateFeed()),
+    url(r'^syndication/template_context/$', feeds.TemplateContextFeed()),
+]

+ 4 - 4
tests/template_tests/alternate_urls.py

@@ -1,12 +1,12 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     # View returning a template response
-    (r'^template_response_view/$', views.template_response_view),
+    url(r'^template_response_view/$', views.template_response_view),
 
     # A view that can be hard to find...
     url(r'^snark/', views.snark, name='snark'),
-)
+]

+ 7 - 8
tests/template_tests/urls.py

@@ -1,20 +1,19 @@
 # coding: utf-8
 from __future__ import unicode_literals
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from . import views
 
 
-urlpatterns = patterns('',
-
+urlpatterns = [
     # Test urls for testing reverse lookups
-    (r'^$', views.index),
-    (r'^client/([\d,]+)/$', views.client),
-    (r'^client/(?P<id>\d+)/(?P<action>[^/]+)/$', views.client_action),
-    (r'^client/(?P<client_id>\d+)/(?P<action>[^/]+)/$', views.client_action),
+    url(r'^$', views.index),
+    url(r'^client/([\d,]+)/$', views.client),
+    url(r'^client/(?P<id>\d+)/(?P<action>[^/]+)/$', views.client_action),
+    url(r'^client/(?P<client_id>\d+)/(?P<action>[^/]+)/$', views.client_action),
     url(r'^named-client/(\d+)/$', views.client2, name="named.client"),
 
     # Unicode strings are permitted everywhere.
     url(r'^Юникод/(\w+)/$', views.client2, name="метка_оператора"),
     url(r'^Юникод/(?P<tag>\S+)/$', 'template_tests.views.client2', name="метка_оператора_2"),
-)
+]

+ 31 - 31
tests/test_client/urls.py

@@ -1,37 +1,37 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 from django.views.generic import RedirectView
 
 from . import views
 
 
-urlpatterns = patterns('',
-    (r'^get_view/$', views.get_view),
-    (r'^post_view/$', views.post_view),
-    (r'^header_view/$', views.view_with_header),
-    (r'^raw_post_view/$', views.raw_post_view),
-    (r'^redirect_view/$', views.redirect_view),
-    (r'^secure_view/$', views.view_with_secure),
-    (r'^permanent_redirect_view/$', RedirectView.as_view(url='/get_view/')),
-    (r'^temporary_redirect_view/$', RedirectView.as_view(url='/get_view/', permanent=False)),
-    (r'^http_redirect_view/$', RedirectView.as_view(url='/secure_view/')),
-    (r'^https_redirect_view/$', RedirectView.as_view(url='https://testserver/secure_view/')),
-    (r'^double_redirect_view/$', views.double_redirect_view),
-    (r'^bad_view/$', views.bad_view),
-    (r'^form_view/$', views.form_view),
-    (r'^form_view_with_template/$', views.form_view_with_template),
-    (r'^formset_view/$', views.formset_view),
-    (r'^login_protected_view/$', views.login_protected_view),
-    (r'^login_protected_method_view/$', views.login_protected_method_view),
-    (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
-    (r'^permission_protected_view/$', views.permission_protected_view),
-    (r'^permission_protected_view_exception/$', views.permission_protected_view_exception),
-    (r'^permission_protected_method_view/$', views.permission_protected_method_view),
-    (r'^session_view/$', views.session_view),
-    (r'^broken_view/$', views.broken_view),
-    (r'^mail_sending_view/$', views.mail_sending_view),
-    (r'^mass_mail_sending_view/$', views.mass_mail_sending_view),
-    (r'^django_project_redirect/$', views.django_project_redirect),
+urlpatterns = [
+    url(r'^get_view/$', views.get_view),
+    url(r'^post_view/$', views.post_view),
+    url(r'^header_view/$', views.view_with_header),
+    url(r'^raw_post_view/$', views.raw_post_view),
+    url(r'^redirect_view/$', views.redirect_view),
+    url(r'^secure_view/$', views.view_with_secure),
+    url(r'^permanent_redirect_view/$', RedirectView.as_view(url='/get_view/')),
+    url(r'^temporary_redirect_view/$', RedirectView.as_view(url='/get_view/', permanent=False)),
+    url(r'^http_redirect_view/$', RedirectView.as_view(url='/secure_view/')),
+    url(r'^https_redirect_view/$', RedirectView.as_view(url='https://testserver/secure_view/')),
+    url(r'^double_redirect_view/$', views.double_redirect_view),
+    url(r'^bad_view/$', views.bad_view),
+    url(r'^form_view/$', views.form_view),
+    url(r'^form_view_with_template/$', views.form_view_with_template),
+    url(r'^formset_view/$', views.formset_view),
+    url(r'^login_protected_view/$', views.login_protected_view),
+    url(r'^login_protected_method_view/$', views.login_protected_method_view),
+    url(r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect),
+    url(r'^permission_protected_view/$', views.permission_protected_view),
+    url(r'^permission_protected_view_exception/$', views.permission_protected_view_exception),
+    url(r'^permission_protected_method_view/$', views.permission_protected_method_view),
+    url(r'^session_view/$', views.session_view),
+    url(r'^broken_view/$', views.broken_view),
+    url(r'^mail_sending_view/$', views.mail_sending_view),
+    url(r'^mass_mail_sending_view/$', views.mass_mail_sending_view),
+    url(r'^django_project_redirect/$', views.django_project_redirect),
 
-    (r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
-    (r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
-)
+    url(r'^accounts/login/$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
+    url(r'^accounts/logout/$', 'django.contrib.auth.views.logout'),
+]

+ 32 - 32
tests/test_client_regress/urls.py

@@ -1,40 +1,40 @@
-from django.conf.urls import patterns, url, include
+from django.conf.urls import url, include
 from django.views.generic import RedirectView
 
 from . import views
 
 
-urlpatterns = patterns('',
-    (r'', include('test_client.urls')),
+urlpatterns = [
+    url(r'', include('test_client.urls')),
 
-    (r'^no_template_view/$', views.no_template_view),
-    (r'^staff_only/$', views.staff_only_view),
-    (r'^get_view/$', views.get_view),
-    (r'^request_data/$', views.request_data),
-    (r'^request_data_extended/$', views.request_data, {'template': 'extended.html', 'data': 'bacon'}),
+    url(r'^no_template_view/$', views.no_template_view),
+    url(r'^staff_only/$', views.staff_only_view),
+    url(r'^get_view/$', views.get_view),
+    url(r'^request_data/$', views.request_data),
+    url(r'^request_data_extended/$', views.request_data, {'template': 'extended.html', 'data': 'bacon'}),
     url(r'^arg_view/(?P<name>.+)/$', views.view_with_argument, name='arg_view'),
     url(r'^nested_view/$', views.nested_view, name='nested_view'),
-    (r'^login_protected_redirect_view/$', views.login_protected_redirect_view),
-    (r'^redirects/$', RedirectView.as_view(url='/redirects/further/')),
-    (r'^redirects/further/$', RedirectView.as_view(url='/redirects/further/more/')),
-    (r'^redirects/further/more/$', RedirectView.as_view(url='/no_template_view/')),
-    (r'^redirect_to_non_existent_view/$', RedirectView.as_view(url='/non_existent_view/')),
-    (r'^redirect_to_non_existent_view2/$', RedirectView.as_view(url='/redirect_to_non_existent_view/')),
-    (r'^redirect_to_self/$', RedirectView.as_view(url='/redirect_to_self/')),
-    (r'^circular_redirect_1/$', RedirectView.as_view(url='/circular_redirect_2/')),
-    (r'^circular_redirect_2/$', RedirectView.as_view(url='/circular_redirect_3/')),
-    (r'^circular_redirect_3/$', RedirectView.as_view(url='/circular_redirect_1/')),
-    (r'^redirect_other_host/$', RedirectView.as_view(url='https://otherserver:8443/no_template_view/')),
-    (r'^set_session/$', views.set_session_view),
-    (r'^check_session/$', views.check_session_view),
-    (r'^request_methods/$', views.request_methods_view),
-    (r'^check_unicode/$', views.return_unicode),
-    (r'^check_binary/$', views.return_undecodable_binary),
-    (r'^parse_unicode_json/$', views.return_json_file),
-    (r'^check_headers/$', views.check_headers),
-    (r'^check_headers_redirect/$', RedirectView.as_view(url='/check_headers/')),
-    (r'^body/$', views.body),
-    (r'^read_all/$', views.read_all),
-    (r'^read_buffer/$', views.read_buffer),
-    (r'^request_context_view/$', views.request_context_view),
-)
+    url(r'^login_protected_redirect_view/$', views.login_protected_redirect_view),
+    url(r'^redirects/$', RedirectView.as_view(url='/redirects/further/')),
+    url(r'^redirects/further/$', RedirectView.as_view(url='/redirects/further/more/')),
+    url(r'^redirects/further/more/$', RedirectView.as_view(url='/no_template_view/')),
+    url(r'^redirect_to_non_existent_view/$', RedirectView.as_view(url='/non_existent_view/')),
+    url(r'^redirect_to_non_existent_view2/$', RedirectView.as_view(url='/redirect_to_non_existent_view/')),
+    url(r'^redirect_to_self/$', RedirectView.as_view(url='/redirect_to_self/')),
+    url(r'^circular_redirect_1/$', RedirectView.as_view(url='/circular_redirect_2/')),
+    url(r'^circular_redirect_2/$', RedirectView.as_view(url='/circular_redirect_3/')),
+    url(r'^circular_redirect_3/$', RedirectView.as_view(url='/circular_redirect_1/')),
+    url(r'^redirect_other_host/$', RedirectView.as_view(url='https://otherserver:8443/no_template_view/')),
+    url(r'^set_session/$', views.set_session_view),
+    url(r'^check_session/$', views.check_session_view),
+    url(r'^request_methods/$', views.request_methods_view),
+    url(r'^check_unicode/$', views.return_unicode),
+    url(r'^check_binary/$', views.return_undecodable_binary),
+    url(r'^parse_unicode_json/$', views.return_json_file),
+    url(r'^check_headers/$', views.check_headers),
+    url(r'^check_headers_redirect/$', RedirectView.as_view(url='/check_headers/')),
+    url(r'^body/$', views.body),
+    url(r'^read_all/$', views.read_all),
+    url(r'^read_buffer/$', views.read_buffer),
+    url(r'^request_context_view/$', views.request_context_view),
+]

+ 3 - 3
tests/test_utils/tests.py

@@ -3,7 +3,7 @@ from __future__ import unicode_literals
 
 import unittest
 
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 from django.core.urlresolvers import reverse
 from django.db import connection
 from django.forms import EmailField, IntegerField
@@ -628,11 +628,11 @@ def fake_view(request):
 
 
 class FirstUrls:
-    urlpatterns = patterns('', url(r'first/$', fake_view, name='first'))
+    urlpatterns = [url(r'first/$', fake_view, name='first')]
 
 
 class SecondUrls:
-    urlpatterns = patterns('', url(r'second/$', fake_view, name='second'))
+    urlpatterns = [url(r'second/$', fake_view, name='second')]
 
 
 class OverrideSettingsTests(TestCase):

+ 5 - 5
tests/test_utils/urls.py

@@ -1,9 +1,9 @@
-from django.conf.urls import patterns
+from django.conf.urls import url
 
 from . import views
 
 
-urlpatterns = patterns('',
-    (r'^test_utils/get_person/(\d+)/$', views.get_person),
-    (r'^test_utils/no_template_used/$', views.no_template_used),
-)
+urlpatterns = [
+    url(r'^test_utils/get_person/(\d+)/$', views.get_person),
+    url(r'^test_utils/no_template_used/$', views.no_template_used),
+]

+ 4 - 4
tests/timezones/urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, include
+from django.conf.urls import include, url
 from django.contrib import admin
 
 from . import admin as tz_admin  # NOQA: register tz_admin
 
-urlpatterns = patterns('',
-    (r'^admin/', include(admin.site.urls)),
-)
+urlpatterns = [
+    url(r'^admin/', include(admin.site.urls)),
+]

+ 3 - 3
tests/urlpatterns_reverse/erroneous_urls.py

@@ -1,6 +1,6 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
-urlpatterns = patterns('',
+urlpatterns = [
     # View has erroneous import
     url(r'erroneous_inner/$', 'urlpatterns_reverse.views.erroneous_view'),
     # Module has erroneous import
@@ -13,4 +13,4 @@ urlpatterns = patterns('',
     url(r'missing_outer/$', 'urlpatterns_reverse.missing_module.missing_view'),
     # Regex contains an error (refs #6170)
     url(r'(regex_error/$', 'regressiontestes.urlpatterns_reverse.views.empty_view'),
-)
+]

+ 3 - 3
tests/urlpatterns_reverse/extra_urls.py

@@ -2,14 +2,14 @@
 Some extra URL patterns that are included at the top level.
 """
 
-from django.conf.urls import patterns, url, include
+from django.conf.urls import url, include
 
 from .views import empty_view
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^e-places/(\d+)/$', empty_view, name='extra-places'),
     url(r'^e-people/(?P<name>\w+)/$', empty_view, name="extra-people"),
     url('', include('urlpatterns_reverse.included_urls2')),
     url(r'^prefix/(?P<prefix>\w+)/', include('urlpatterns_reverse.included_urls2')),
-)
+]

+ 4 - 4
tests/urlpatterns_reverse/included_named_urls.py

@@ -1,11 +1,11 @@
-from django.conf.urls import patterns, url, include
+from django.conf.urls import url, include
 
 from .views import empty_view
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^$', empty_view, name="named-url3"),
     url(r'^extra/(?P<extra>\w+)/$', empty_view, name="named-url4"),
     url(r'^(?P<one>\d+)|(?P<two>\d+)/$', empty_view),
-    (r'^included/', include('urlpatterns_reverse.included_named_urls2')),
-)
+    url(r'^included/', include('urlpatterns_reverse.included_named_urls2')),
+]

+ 3 - 3
tests/urlpatterns_reverse/included_named_urls2.py

@@ -1,10 +1,10 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from .views import empty_view
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^$', empty_view, name="named-url5"),
     url(r'^extra/(?P<extra>\w+)/$', empty_view, name="named-url6"),
     url(r'^(?P<one>\d+)|(?P<two>\d+)/$', empty_view),
-)
+]

+ 17 - 11
tests/urlpatterns_reverse/included_namespace_urls.py

@@ -1,3 +1,5 @@
+import warnings
+
 from django.conf.urls import patterns, url, include
 
 from .namespace_urls import URLObject
@@ -6,18 +8,22 @@ from .views import view_class_instance
 
 testobj3 = URLObject('testapp', 'test-ns3')
 
-urlpatterns = patterns('urlpatterns_reverse.views',
-    url(r'^normal/$', 'empty_view', name='inc-normal-view'),
-    url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='inc-normal-view'),
+# test deprecated patterns() function. convert to list of urls() in Django 2.0
+with warnings.catch_warnings(record=True) as w:
+    warnings.filterwarnings('ignore', module='django.conf.urls')
+
+    urlpatterns = patterns('urlpatterns_reverse.views',
+        url(r'^normal/$', 'empty_view', name='inc-normal-view'),
+        url(r'^normal/(?P<arg1>\d+)/(?P<arg2>\d+)/$', 'empty_view', name='inc-normal-view'),
 
-    url(r'^\+\\\$\*/$', 'empty_view', name='inc-special-view'),
+        url(r'^\+\\\$\*/$', 'empty_view', name='inc-special-view'),
 
-    url(r'^mixed_args/(\d+)/(?P<arg2>\d+)/$', 'empty_view', name='inc-mixed-args'),
-    url(r'^no_kwargs/(\d+)/(\d+)/$', 'empty_view', name='inc-no-kwargs'),
+        url(r'^mixed_args/(\d+)/(?P<arg2>\d+)/$', 'empty_view', name='inc-mixed-args'),
+        url(r'^no_kwargs/(\d+)/(\d+)/$', 'empty_view', name='inc-no-kwargs'),
 
-    url(r'^view_class/(?P<arg1>\d+)/(?P<arg2>\d+)/$', view_class_instance, name='inc-view-class'),
+        url(r'^view_class/(?P<arg1>\d+)/(?P<arg2>\d+)/$', view_class_instance, name='inc-view-class'),
 
-    (r'^test3/', include(testobj3.urls)),
-    (r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')),
-    (r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')),
-)
+        (r'^test3/', include(testobj3.urls)),
+        (r'^ns-included3/', include('urlpatterns_reverse.included_urls', namespace='inc-ns3')),
+        (r'^ns-included4/', include('urlpatterns_reverse.namespace_urls', namespace='inc-ns4')),
+    )

+ 3 - 3
tests/urlpatterns_reverse/included_no_kwargs_urls.py

@@ -1,8 +1,8 @@
-from django.conf.urls import patterns, url
+from django.conf.urls import url
 
 from .views import empty_view
 
 
-urlpatterns = patterns('',
+urlpatterns = [
     url(r'^inner-no-kwargs/(\d+)/', empty_view, name="inner-no-kwargs")
-)
+]

Some files were not shown because too many files changed in this diff