Opened 14 years ago
Closed 14 years ago
#15645 closed (duplicate)
HTTP methods in urls.py
Reported by: | Matt Harasymczuk | Owned by: | nobody |
---|---|---|---|
Component: | HTTP handling | Version: | |
Severity: | Keywords: | http urls | |
Cc: | Triage Stage: | Design decision needed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It would be nice to have possibility to distinguish a HTTP method in urls.py.
IMHO it would be clearer and more extensible in future
for example:
urlpatterns = patterns('', url ('POST', r'/user/(?P<username>\d+)$', 'myapp.views.user.view1'), url ('GET', r'/user/(?P<username>\d+)$', 'myapp.views.user.view2'), url ('DELETE', r'/user/(?P<username>\d+)$', 'myapp.views.user.delete'), )
Change History (6)
comment:1 by , 14 years ago
Triage Stage: | Unreviewed → Design decision needed |
---|
comment:2 by , 14 years ago
it could be backward compatible.
if it would work only if there is an url() function, not simple list ()
and url will check for its first param, if it is HTTP method GET, PUT, DELETE, POST, etc, then do action with regex and view
it not, do the old way
However I think it is not necessary complicated.
I suggest a http function:
urlpatterns = patterns('', http ('POST', r'/user/(?P<username>\d+)$', 'myapp.views.user.view1'), http ('GET', r'/user/(?P<username>\d+)$', 'myapp.views.user.view2'), http ('DELETE', r'/user/(?P<username>\d+)$', 'myapp.views.user.delete'), )
and url do the same as it is now
comment:3 by , 14 years ago
I know that this maybe encumber an urlpatterns but consider this:
from django.conf.urls.defaults import http from django.conf.urls.defaults import url from django.conf.urls.defaults import patterns from django.conf.urls.defaults import include from django.contrib import admin urlpatterns = patterns('myapp', http.ajax (r'/user/(?P<username>\d+)$', 'views.view1'), http.post (r'/user/(?P<username>\d+)$', 'views.view2'), http.get (r'/user/(?P<username>\d+)$', 'views.view2'), http.delete (r'/user/(?P<username>\d+)$', 'views.delete'), # an url function will do the old way url (r'^', include(admin.site.urls)), )
or equivalent
from django.conf.urls.defaults import http from django.conf.urls.defaults import url from django.conf.urls.defaults import patterns from django.conf.urls.defaults import include from django.contrib import admin urlpatterns = patterns('myapp', http ('POST', r'/user/(?P<username>\d+)$', 'views.view1'), http ('GET', r'/user/(?P<username>\d+)$', 'views.view2'), http ('DELETE', r'/user/(?P<username>\d+)$', 'views.delete'), # an url function will do the old way url (r'^', include(admin.site.urls)), )
therefore maybe a request not http module name is better to consider
IMHO:
first (http.ajax, http.get, http.post...) solution is the most clear and the best fit to the explicit python policy
it is simple and I think it would boost urls dispatcher performance
when it may easy and fast filter lot of regexp pattern, hence there is no need to lookup in POST list regexps when we have a GET request
maybe distinguishing of ajax methods isn't a bad idea too:
from django.conf.urls.defaults import ajax from django.conf.urls.defaults import patterns urlpatterns = patterns('myapp', ajax.post (r'/user/(?P<username>\d+)$', 'views.view2'), ajax.get (r'/user/(?P<username>\d+)$', 'views.view2'), ajax.delete (r'/user/(?P<username>\d+)$', 'views.delete'), )
It gives a little logic to urls.py but gives a performance, simplicity and readability in return
this in conclusion would give us:
from django.conf.urls.defaults import ajax from django.conf.urls.defaults import http from django.conf.urls.defaults import url from django.conf.urls.defaults import patterns from django.conf.urls.defaults import include from django.contrib import admin urlpatterns = patterns('myapp', ajax.post (r'/user/(?P<username>\d+)$', 'views.viewAjax1'), ajax.get (r'/user/(?P<username>\d+)$', 'views.viewAjax2'), ajax.delete (r'/user/(?P<username>\d+)$', 'views.delete'), ajax.all (r'/user/(?P<username>\d+)$', 'views.delete'), #all type of methods ajax (r'/user/(?P<username>\d+)$', 'views.delete'), #all type of methods ajax ('POST', r'/user/(?P<username>\d+)$', 'views.view2'), ajax ('GET', r'/user/(?P<username>\d+)$', 'views.view2'), ajax ('DELETE', r'/user/(?P<username>\d+)$', 'views.view2'), http.post (r'/user/(?P<username>\d+)$', 'views.view2'), http.get (r'/user/(?P<username>\d+)$', 'views.view2'), http.delete (r'/user/(?P<username>\d+)$', 'views.delete'), http (r'/user/(?P<username>\d+)$', 'views.delete'), #all type of methods http ('POST', r'/user/(?P<username>\d+)$', 'views.view2') http ('GET', r'/user/(?P<username>\d+)$', 'views.view2') http ('DELETE', r'/user/(?P<username>\d+)$', 'views.view2') # an url function will do the old way url (r'^', include(admin.site.urls)), )
comment:4 by , 14 years ago
Unless I'm misreading the code, method based dispatch already exists in one form, implemented in the new Class Based Views (see View in django.views.generic.base).
As such, implementing the same basic functionality elsewhere (even if its a better fit, which the urls configuration may well be) seems counter-intuitive, and against the oft harkened zen of there being only one true way.
comment:5 by , 14 years ago
Class Based Views View.dsipatch does not provide such clear and intuitive way of defining urls.
And require an application to run view to check if it able to handle a request.
IMHO this way gives you better scalability performance and easy of use.
Look at those sample code (I am thinking about last one), and you know already which view is when executed, without having to see the inner code of any classes and views.
When you look at somebody's else project you are not hoping to read views to see how one url is handled.
When request is POST it looks up in POST urls and quickly omit not fitting GET and DELETE methods.
My function views are full of those ifs:
if request.is_ajax: #do stuff else: if request.method == "POST": #do something else: #do else
Hence my true code is almost two indents inside those boilerplate if structure.
Which is always the same... it takes a lot of python beauty and readibility from code.
I know I am able to do
urlpatterns = patterns('myapp', url (r'/ajax/user/(?P<username>\d+)', 'views.myview'), url (r'/post/user/(?P<username>\d+)', 'views.myview'), url (r'/get/user/(?P<username>\d+)', 'views.myview'), url (r'/delete/user/(?P<username>\d+)', 'views.myview'), )
but what with reusability?
We have to change this to something like r'/user/post/...' and r'/user/get/...'
When first part of url determines app the second will have to be a method... and so on.
Every django setup has completely different approach to handle urls. Therefore I think that this standardization I mention in my second post will solve problem, at least will provide a reasonable and logic way do define urls.
Everywhere when I am looking for, people is talking about distinguishing methods inside view in nested ifs... I find it ugly, and necessary. IMHO urls dispatcher (the name dispatcher defines it!) should do this stuff.
Not some kind of inner class based views magic. I think that magic belongs to ruby and RoR, and explicit is the true pythonic way.
BTW. How this dispatch method got inside class based views?
Isn't it suppose to be in some kind of dispatcher in modules? IMHO its logically do not fit to the Class Based Views.
What do you think?
comment:6 by , 14 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
This looks like #2784, but with different syntax. As a side note, django-developers is usually a better place for longer discussions like this one.
Why not, although the suggested API would not be backwards compatible. Also, if the method didn't match then a 404 would systematically be returned, which is quite restrained. Marking DDN for now.