#22218 closed Cleanup/optimization (fixed)
Deprecate 'prefix' arg to django.conf.urls.patterns
Reported by: | Carl Meyer | Owned by: | Tim Graham |
---|---|---|---|
Component: | Core (URLs) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | loic@…, Simon Charette | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
In the olden days of Django, it was encouraged to reference views as strings in url patterns:
urlpatterns = patterns('', url('^$', 'myapp.views.myview'), )
and Django would magically import "myapp.views.myview" internally and turn the string into a real function reference.
In order to reduce repetition when referencing many views from the same module, the patterns
function takes a required initial "prefix" arg, which is prepended to all views-as-strings in that set of url patterns:
urlpatterns = patterns('myapp.views', url('^$', 'myview'), url('^other/$', 'otherview'), )
In the modern era, we have updated the tutorial to instead recommend actually importing your views module and referencing your view functions (or classes) directly. This has a number of advantages, all deriving from the fact that we are now using Normal Python in place of Django String Magic: the errors when you mistype a view name are less obscure, IDEs can help with autocompleting view names, etc.
With the advent of the class-based generic views, it is even more likely that users are referencing view callables directly in their urlconf, due to the need to call .as_view()
.
So these days, the above use of the prefix arg is much more likely to be written (and is better written) as:
from myapp import views urlpatterns = patterns('', url('^$', views.myview), url('^other/$', views.otherview), )
This leaves the 'prefix' arg in modern Django code as a useless empty string that has to be passed to every invocation of patterns
. This is an ugly API wart, and a burden when teaching new users (answering the newbie's question "why do I need this empty string as the first argument to patterns?" requires either a time-wasting detour into the history of Django URLconfs or a hand-wavy "don't worry, just do it").
I suggest that we deprecate this argument. This will require type-checking the first argument to patterns
for the duration of the deprecation period, but I don't think that's so bad.
(I would not be opposed to deprecating the entire views-as-strings feature, but the additional gain there is only code we can remove and stop maintaining, not a benefit to the public API, so I decided to keep this proposal minimal. If there's consensus to deprecate the entire feature, I will happily update the summary to reflect that.)
Change History (10)
comment:1 by , 11 years ago
Cc: | added |
---|---|
Triage Stage: | Unreviewed → Accepted |
Version: | 1.6 → master |
comment:2 by , 11 years ago
Agreed we should get rid of prefix. I've got some ideas around which actually involve changing URLconfs and resolving/reversing more completely. In particular, if we deprecate prefix
on patterns, then at least 50% of the use case of url()
rather than RegexURLResolver
is unneeded.
*<Going a bit off the real topic of this ticket now, but it's kinda related>*
On the topic of beginners, I've heard a number of complaints about the fact the only built in method of producing urls is regexes. Whilst these are very powerful, learning the (somewhat obscure) syntax of (?P<poll_id>\d+)
and remembering it every time you want to write a URL is a non-trivial hurdle (and that's before you start on the differing behaviour of \w
on Py2/3). Perhaps we should include a solution similar to https://github.com/oinopion/hurl
Another irritation of mine is django.conf.urls
vs django.core.urlresolvers
- everything should live in django.urls
.
Also, the syntax for django.shortcuts.reverse
is much better than that of django.core.urlresolvers.reverse
- the kwargs={}
pattern is annoying as (generally) you don't use args in a urlpattern.
Other related issues (which may or may not be resolved) are:
- The sea of
handlerXXX
functions (and being able to customise these dependent on the patterns - API views vs real views) - The general weirdness of namespacing (currently a powerful solution but 90% of use cases don't need the complexity)
- The ability to decorate views at the patterns level (rather than each view individually)
- Deprecate models.permalink
- Our "absolute urls" are not absolute
- Reversing by dotted path to view is just a bad idea
I haven't yet decided what the new API should look like, but a significant advantage of putting it in django.urls
is all the main public functions can stay exactly as they are for deprecation and proxy to the new version. People using RegexURLResolver
directly might have issues, but that can likely be worked around as well. This probably needs a django-dev discussion.
For the sake of clarity, I'm not against fixing this ticket on its own, I think there's some value in it. However I would like (at some point) to "fix" url resolving in general. This whole section of the code base (and its design) are very old, and it might be worth reworking the whole thing, rather than adding type checking on first arguments for a while.
comment:3 by , 11 years ago
Cc: | added |
---|
What about deprecating django.conf.urls.patterns
altogether? If we remove support for the prefix
argument I see no compelling reason of keeping it around.
Updating the documentation to use a list of url
s instead should be straightforward.
from myapp import views urlpatterns = [ url('^$', views.myview), url('^other/$', views.otherview), ]
comment:4 by , 11 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
+1 to deprecating patterns
entirely. I've started working on this. The other thing that patterns
provides besides the prefix
parameter is automatically wrapping plain tuples in urlpatterns
in url()
. I think removing this and forcing usage of url()
will be a good cleanup.
comment:5 by , 11 years ago
Any thoughts about what we should do about django.conf.urls.i18n.i18n_patterns
?
I don't use it, but it looks like deprecating its call to patterns
might work.
def i18n_patterns(prefix, *args): """ Adds the language code prefix to every URL pattern within this function. This may only be used in the root URLconf, not in an included URLconf. """ pattern_list = patterns(prefix, *args) if not settings.USE_I18N: return pattern_list return [LocaleRegexURLResolver(pattern_list)]
comment:6 by , 11 years ago
Has patch: | set |
---|
I will answer my own question and say we should deprecate just the prefix
argument to i18n_patterns()
.
PR is ready for final review.
comment:8 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
+1 for this cleanup, I always considered
prefix
an anti-pattern.