Fixed #26431 -- Prevented django.urls.resolve() from returning missing optional parameters.

Previous behavior was inconsistent with django.urls.reverse() and
caused that translate_url() created an incorrect URL when an optional
parameter was missing.
This commit is contained in:
daniel a rios 2019-04-24 22:51:47 +02:00 committed by Mariusz Felisiak
parent d640c71fa3
commit 76b993a117
3 changed files with 17 additions and 5 deletions

View File

@ -153,7 +153,7 @@ 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 = match.groupdict()
kwargs = {k: v for k, v in match.groupdict().items() if v is not None}
args = () if kwargs else match.groups()
return path[match.end():], args, kwargs
return None

View File

@ -159,6 +159,10 @@ class URLTranslationTests(URLTestCaseBase):
self.assertEqual(translate_url('/en/account/register-as-path/', 'nl'), '/nl/profiel/registreren-als-pad/')
self.assertEqual(translation.get_language(), 'en')
# URL with parameters.
self.assertEqual(
translate_url('/en/with-arguments/regular-argument/', 'nl'),
'/nl/with-arguments/regular-argument/',
)
self.assertEqual(
translate_url('/en/with-arguments/regular-argument/optional.html', 'nl'),
'/nl/with-arguments/regular-argument/optional.html',

View File

@ -55,10 +55,18 @@ class SimplifiedURLTests(SimpleTestCase):
self.assertEqual(match.route, '^regex/(?P<pk>[0-9]+)/$')
def test_re_path_with_optional_parameter(self):
match = resolve('/regex_optional/1/2/')
self.assertEqual(match.url_name, 'regex_optional')
self.assertEqual(match.kwargs, {'arg1': '1', 'arg2': '2'})
self.assertEqual(match.route, r'^regex_optional/(?P<arg1>\d+)/(?:(?P<arg2>\d+)/)?')
for url, kwargs in (
('/regex_optional/1/2/', {'arg1': '1', 'arg2': '2'}),
('/regex_optional/1/', {'arg1': '1'}),
):
with self.subTest(url=url):
match = resolve(url)
self.assertEqual(match.url_name, 'regex_optional')
self.assertEqual(match.kwargs, kwargs)
self.assertEqual(
match.route,
r'^regex_optional/(?P<arg1>\d+)/(?:(?P<arg2>\d+)/)?',
)
def test_path_lookup_with_inclusion(self):
match = resolve('/included_urls/extra/something/')