summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMariusz Felisiak <felisiak.mariusz@gmail.com>2019-12-06 09:32:51 +0100
committerGitHub <noreply@github.com>2019-12-06 09:32:51 +0100
commit82a88d2f48e13ef5d472741d5ed1c183230cfe4c (patch)
tree8f407a9e34c0a7b7d62d3e370bc7592693b08e94
parentf138e75910b1e541686c4dce3d8f467f6fc234cb (diff)
Fixed #31061 -- Ignored positional args in django.urls.resolve() when all optional named parameters are missing.
Regression in 76b993a117b61c41584e95149a67d8a1e9f49dd1. Thanks Claude Paroz for the report and Carlton Gibson for reviews.
-rw-r--r--django/urls/resolvers.py3
-rw-r--r--docs/releases/3.0.1.txt4
-rw-r--r--docs/topics/http/urls.txt2
-rw-r--r--tests/urlpatterns/path_urls.py5
-rw-r--r--tests/urlpatterns/tests.py10
5 files changed, 22 insertions, 2 deletions
diff --git a/django/urls/resolvers.py b/django/urls/resolvers.py
index 2d4610aac4..120e0396af 100644
--- a/django/urls/resolvers.py
+++ b/django/urls/resolvers.py
@@ -158,8 +158,9 @@ class RegexPattern(CheckURLMixin):
# If there are any named groups, use those as kwargs, ignoring
# non-named groups. Otherwise, pass all non-named arguments as
# positional arguments.
- kwargs = {k: v for k, v in match.groupdict().items() if v is not None}
+ kwargs = match.groupdict()
args = () if kwargs else match.groups()
+ kwargs = {k: v for k, v in kwargs.items() if v is not None}
return path[match.end():], args, kwargs
return None
diff --git a/docs/releases/3.0.1.txt b/docs/releases/3.0.1.txt
index 589ef40499..cdfdc33e40 100644
--- a/docs/releases/3.0.1.txt
+++ b/docs/releases/3.0.1.txt
@@ -13,3 +13,7 @@ Bugfixes
inside Jupyter and other environments that force an async context, by adding
and option to disable :ref:`async-safety` mechanism with
``DJANGO_ALLOW_ASYNC_UNSAFE`` environment variable (:ticket:`31056`).
+
+* Fixed a regression in Django 3.0 where ``RegexPattern``, used by
+ :func:`~django.urls.re_path`, returned positional arguments to be passed to
+ the view when all optional named groups were missing (:ticket:`31061`).
diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt
index 4283d6ebe1..5c1540b809 100644
--- a/docs/topics/http/urls.txt
+++ b/docs/topics/http/urls.txt
@@ -53,7 +53,7 @@ algorithm the system follows to determine which Python code to execute:
arguments:
* An instance of :class:`~django.http.HttpRequest`.
- * If the matched URL pattern returned no named groups, then the
+ * If the matched URL pattern contained no named groups, then the
matches from the regular expression are provided as positional arguments.
* The keyword arguments are made up of any named parts matched by the
path expression, overridden by any arguments specified in the optional
diff --git a/tests/urlpatterns/path_urls.py b/tests/urlpatterns/path_urls.py
index b40801b39d..afc15f30af 100644
--- a/tests/urlpatterns/path_urls.py
+++ b/tests/urlpatterns/path_urls.py
@@ -12,6 +12,11 @@ urlpatterns = [
path('included_urls/', include('urlpatterns.included_urls')),
re_path(r'^regex/(?P<pk>[0-9]+)/$', views.empty_view, name='regex'),
re_path(r'^regex_optional/(?P<arg1>\d+)/(?:(?P<arg2>\d+)/)?', views.empty_view, name='regex_optional'),
+ re_path(
+ r'^regex_only_optional/(?:(?P<arg1>\d+)/)?',
+ views.empty_view,
+ name='regex_only_optional',
+ ),
path('', include('urlpatterns.more_urls')),
path('<lang>/<path:url>/', views.empty_view, name='lang-and-path'),
]
diff --git a/tests/urlpatterns/tests.py b/tests/urlpatterns/tests.py
index 92c4e6399e..b149e0d512 100644
--- a/tests/urlpatterns/tests.py
+++ b/tests/urlpatterns/tests.py
@@ -68,6 +68,16 @@ class SimplifiedURLTests(SimpleTestCase):
r'^regex_optional/(?P<arg1>\d+)/(?:(?P<arg2>\d+)/)?',
)
+ def test_re_path_with_missing_optional_parameter(self):
+ match = resolve('/regex_only_optional/')
+ self.assertEqual(match.url_name, 'regex_only_optional')
+ self.assertEqual(match.kwargs, {})
+ self.assertEqual(match.args, ())
+ self.assertEqual(
+ match.route,
+ r'^regex_only_optional/(?:(?P<arg1>\d+)/)?',
+ )
+
def test_path_lookup_with_inclusion(self):
match = resolve('/included_urls/extra/something/')
self.assertEqual(match.url_name, 'inner-extra')