mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Fixed #31061 -- Ignored positional args in django.urls.resolve() when all optional named parameters are missing.
Regression in 76b993a117.
Thanks Claude Paroz for the report and Carlton Gibson for reviews.
			
			
This commit is contained in:
		| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -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`). | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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'), | ||||
| ] | ||||
|   | ||||
| @@ -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') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user