1
0
mirror of https://github.com/django/django.git synced 2025-10-24 22:26:08 +00:00

Fixed #28593 -- Added a simplified URL routing syntax per DEP 0201.

Thanks Aymeric Augustin for shepherding the DEP and patch review.
Thanks Marten Kenbeek and Tim Graham for contributing to the code.
Thanks Tom Christie, Shai Berger, and Tim Graham for the docs.
This commit is contained in:
Sjoerd Job Postmus
2016-10-20 19:29:04 +02:00
committed by Tim Graham
parent c4c128d67c
commit df41b5a05d
77 changed files with 1663 additions and 1105 deletions

View File

@@ -567,7 +567,7 @@ class ModelAdmin(BaseModelAdmin):
return inline_instances
def get_urls(self):
from django.conf.urls import url
from django.urls import path
def wrap(view):
def wrapper(*args, **kwargs):
@@ -578,14 +578,14 @@ class ModelAdmin(BaseModelAdmin):
info = self.model._meta.app_label, self.model._meta.model_name
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'^autocomplete/$', wrap(self.autocomplete_view), name='%s_%s_autocomplete' % 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'^(.+)/change/$', wrap(self.change_view), name='%s_%s_change' % info),
path('', wrap(self.changelist_view), name='%s_%s_changelist' % info),
path('add/', wrap(self.add_view), name='%s_%s_add' % info),
path('autocomplete/', wrap(self.autocomplete_view), name='%s_%s_autocomplete' % info),
path('<path:object_id>/history/', wrap(self.history_view), name='%s_%s_history' % info),
path('<path:object_id>/delete/', wrap(self.delete_view), name='%s_%s_delete' % info),
path('<path:object_id>/change/', wrap(self.change_view), name='%s_%s_change' % info),
# For backwards compatibility (was the change url before 1.9)
url(r'^(.+)/$', wrap(RedirectView.as_view(
path('<path:object_id>/', wrap(RedirectView.as_view(
pattern_name='%s:%s_%s_change' % ((self.admin_site.name,) + info)
))),
]
@@ -1173,8 +1173,7 @@ class ModelAdmin(BaseModelAdmin):
opts = obj._meta
to_field = request.POST.get(TO_FIELD_VAR)
attr = str(to_field) if to_field else opts.pk.attname
# Retrieve the `object_id` from the resolved pattern arguments.
value = request.resolver_match.args[0]
value = request.resolver_match.kwargs['object_id']
new_value = obj.serializable_value(attr)
popup_response_data = json.dumps({
'action': 'change',

View File

@@ -196,11 +196,11 @@ class AdminSite:
class MyAdminSite(AdminSite):
def get_urls(self):
from django.conf.urls import url
from django.urls import path
urls = super().get_urls()
urls += [
url(r'^my_view/$', self.admin_view(some_view))
path('my_view/', self.admin_view(some_view))
]
return urls
@@ -230,7 +230,7 @@ class AdminSite:
return update_wrapper(inner, view)
def get_urls(self):
from django.conf.urls import url, include
from django.urls import include, path, re_path
# 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.
@@ -244,15 +244,21 @@ class AdminSite:
# Admin-site-wide views.
urlpatterns = [
url(r'^$', wrap(self.index), name='index'),
url(r'^login/$', self.login, name='login'),
url(r'^logout/$', wrap(self.logout), name='logout'),
url(r'^password_change/$', wrap(self.password_change, cacheable=True), name='password_change'),
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'),
path('', wrap(self.index), name='index'),
path('login/', self.login, name='login'),
path('logout/', wrap(self.logout), name='logout'),
path('password_change/', wrap(self.password_change, cacheable=True), name='password_change'),
path(
'password_change/done/',
wrap(self.password_change_done, cacheable=True),
name='password_change_done',
),
path('jsi18n/', wrap(self.i18n_javascript, cacheable=True), name='jsi18n'),
path(
'r/<int:content_type_id>/<path: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
@@ -260,7 +266,7 @@ class AdminSite:
valid_app_labels = []
for model, model_admin in self._registry.items():
urlpatterns += [
url(r'^%s/%s/' % (model._meta.app_label, model._meta.model_name), include(model_admin.urls)),
path('%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)
@@ -270,7 +276,7 @@ class AdminSite:
if valid_app_labels:
regex = r'^(?P<app_label>' + '|'.join(valid_app_labels) + ')/$'
urlpatterns += [
url(regex, wrap(self.app_index), name='app_list'),
re_path(regex, wrap(self.app_index), name='app_list'),
]
return urlpatterns

View File

@@ -1,32 +1,50 @@
from django.conf.urls import url
from django.contrib.admindocs import views
from django.urls import path, re_path
urlpatterns = [
url(r'^$',
path(
'',
views.BaseAdminDocsView.as_view(template_name='admin_doc/index.html'),
name='django-admindocs-docroot'),
url(r'^bookmarklets/$',
name='django-admindocs-docroot',
),
path(
'bookmarklets/',
views.BookmarkletsView.as_view(),
name='django-admindocs-bookmarklets'),
url(r'^tags/$',
name='django-admindocs-bookmarklets',
),
path(
'tags/',
views.TemplateTagIndexView.as_view(),
name='django-admindocs-tags'),
url(r'^filters/$',
name='django-admindocs-tags',
),
path(
'filters/',
views.TemplateFilterIndexView.as_view(),
name='django-admindocs-filters'),
url(r'^views/$',
name='django-admindocs-filters',
),
path(
'views/',
views.ViewIndexView.as_view(),
name='django-admindocs-views-index'),
url(r'^views/(?P<view>[^/]+)/$',
name='django-admindocs-views-index',
),
path(
'views/<view>/',
views.ViewDetailView.as_view(),
name='django-admindocs-views-detail'),
url(r'^models/$',
name='django-admindocs-views-detail',
),
path(
'models/',
views.ModelIndexView.as_view(),
name='django-admindocs-models-index'),
url(r'^models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$',
name='django-admindocs-models-index',
),
re_path(
r'^models/(?P<app_label>[^\.]+)\.(?P<model_name>[^/]+)/$',
views.ModelDetailView.as_view(),
name='django-admindocs-models-detail'),
url(r'^templates/(?P<template>.*)/$',
name='django-admindocs-models-detail',
),
path(
'templates/<path:template>/',
views.TemplateDetailView.as_view(),
name='django-admindocs-templates'),
name='django-admindocs-templates',
),
]

View File

@@ -401,13 +401,12 @@ def extract_views_from_urlpatterns(urlpatterns, base='', namespace=None):
continue
views.extend(extract_views_from_urlpatterns(
patterns,
base + p.regex.pattern,
base + str(p.pattern),
(namespace or []) + (p.namespace and [p.namespace] or [])
))
elif hasattr(p, 'callback'):
try:
views.append((p.callback, base + p.regex.pattern,
namespace, p.name))
views.append((p.callback, base + str(p.pattern), namespace, p.name))
except ViewDoesNotExist:
continue
else:

View File

@@ -1,5 +1,4 @@
from django.conf import settings
from django.conf.urls import url
from django.contrib import admin, messages
from django.contrib.admin.options import IS_POPUP_VAR
from django.contrib.admin.utils import unquote
@@ -12,7 +11,7 @@ from django.core.exceptions import PermissionDenied
from django.db import router, transaction
from django.http import Http404, HttpResponseRedirect
from django.template.response import TemplateResponse
from django.urls import reverse
from django.urls import path, reverse
from django.utils.decorators import method_decorator
from django.utils.html import escape
from django.utils.translation import gettext, gettext_lazy as _
@@ -81,8 +80,8 @@ class UserAdmin(admin.ModelAdmin):
def get_urls(self):
return [
url(
r'^(.+)/password/$',
path(
'<id>/password/',
self.admin_site.admin_view(self.user_change_password),
name='auth_user_password_change',
),

View File

@@ -3,19 +3,18 @@
# It is also provided as a convenience to those who want to deploy these URLs
# elsewhere.
from django.conf.urls import url
from django.contrib.auth import views
from django.urls import path
urlpatterns = [
url(r'^login/$', views.LoginView.as_view(), name='login'),
url(r'^logout/$', views.LogoutView.as_view(), name='logout'),
path('login/', views.LoginView.as_view(), name='login'),
path('logout/', views.LogoutView.as_view(), name='logout'),
url(r'^password_change/$', views.PasswordChangeView.as_view(), name='password_change'),
url(r'^password_change/done/$', views.PasswordChangeDoneView.as_view(), name='password_change_done'),
path('password_change/', views.PasswordChangeView.as_view(), name='password_change'),
path('password_change/done/', views.PasswordChangeDoneView.as_view(), name='password_change_done'),
url(r'^password_reset/$', views.PasswordResetView.as_view(), name='password_reset'),
url(r'^password_reset/done/$', views.PasswordResetDoneView.as_view(), 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})/$',
views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
url(r'^reset/done/$', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
path('password_reset/', views.PasswordResetView.as_view(), name='password_reset'),
path('password_reset/done/', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
path('reset/<uidb64>/<token>/', views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
path('reset/done/', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

View File

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