#33351: URLPattern should have a guard/check for arguments.
-------------------------------------+-------------------------------------
Reporter: Keryn | Owner: nobody
Knight |
Type: New | Status: new
feature |
Component: Core | Version: dev
(URLs) | Keywords: path _path
Severity: Normal | URLPattern check
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Apparently, however many years into using Django, I'm still capable of
making a "newbie" mistake and getting confused. So perhaps other actual
new users encounter similar, especially given the lack of typing
specifiers.
I defined a URL like so:
{{{
urlpatterns = [
path("path/to/thing", MyView.as_view(), "my_view"),
]
}}}
which ... well, you either spot the issue immediately or you don't, and
end up with the following. If you try and `resolve()` the path (eg: by
making a request in your browser), you'll get something like:
{{{
In [3]: resolve("/path/to/thing")
~/Code/django/django/urls/base.py in resolve(path, urlconf)
22 if urlconf is None:
23 urlconf = get_urlconf()
---> 24 return get_resolver(urlconf).resolve(path)
25
26
~/Code/django/django/urls/resolvers.py in resolve(self, path)
586 for pattern in self.url_patterns:
587 try:
--> 588 sub_match = pattern.resolve(new_path)
589 except Resolver404 as e:
590 self._extend_tried(tried, pattern,
e.args[0].get('tried'))
~/Code/django/django/urls/resolvers.py in resolve(self, path)
388 new_path, args, kwargs = match
389 # Pass any extra_kwargs as **kwargs.
--> 390 kwargs.update(self.default_args)
391 return ResolverMatch(self.callback, args, kwargs,
self.pattern.name, route=str(self.pattern))
392
ValueError: dictionary update sequence element #0 has length 1; 2 is
required
}}}
The crux of the issue being that I ''meant'' to give the URL a name, and
it's a super unfortunate history that `kwargs` comes ''before'' the `name`
argument (because nearly everyone gives a URL a name, but passing static
kwargs is ''comparatively'' infrequent). So what's actually happened is
that `kwargs = "my_view"` and eventually `self.default_args = "my_view"`.
If I update to `path("path/to/thing", MyView.as_view(), "my_view",
name="my_view")`, leaving the type incorrect, I can get the following
error via reverse, too:
{{{
In [4]: reverse("my_view")
~/Code/django/django/urls/base.py in reverse(viewname, urlconf, args,
kwargs, current_app)
84 resolver = get_ns_resolver(ns_pattern, resolver,
tuple(ns_converters.items()))
85
---> 86 return resolver._reverse_with_prefix(view, prefix, *args,
**kwargs)
87
88
~/Code/django/django/urls/resolvers.py in _reverse_with_prefix(self,
lookup_view, _prefix, *args, **kwargs)
669 if
set(kwargs).symmetric_difference(params).difference(defaults):
670 continue
--> 671 if any(kwargs.get(k, v) != v for k, v in
defaults.items()):
672 continue
673 candidate_subs = kwargs
AttributeError: 'str' object has no attribute 'items'
}}}
Both of these suggest that either there should be a type-guard in `_path`
to assert it's ''dict-ish'' (if not `None`), or a system check on
`URLPattern` to raise a friendly message. Well, they actually continue to
suggest to me that everything after the `view` argument should be keyword-
only, or that kwargs should come later, but I suspect those to be a harder
sell ;)
This is specifically around the `kwargs`, but it doesn't look like there's
any guarding on the `name` either, and I feel like a name of `{'test':
'test'}` (i.e. accidentally swapped both positionals) is likely to bite &
cause an issue somewhere.
--
Ticket URL: <https://code.djangoproject.com/ticket/33351>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/052.c6fb0b191ebe9727a83111c28c22e4d6%40djangoproject.com.