I think following code is inefficient and does the same as urls.py
does with URL of requests:
# urls.py
urlpatterns = patterns('',
(r'^goods/', 'mysite.goods.views.goods'),
)
# views.py
def goods(request):
if request.method == 'GET':
return goods_show(request)
elif request.method == 'PUT':
return goods_create(request)
elif request.method == 'POST'
return goods_update(request)
elif request.method == 'DELETE':
return goods_delete(request)
We can just add a method filter like we do with request URL. Then
urls.py will look something like that:
urlpatterns = patterns('',
('*', r'^django/admin/', include('django.contrib.admin.urls')),
('GET', r'^django/polls/(?P<id>\d+)/', 'mysite.polls.views.show'),
('PUT', r'^django/polls/', 'mysite.polls.views.create'),
('POST', r'^django/polls/(?P<id>\d+)/',
'mysite.polls.views.update'),
('DELETE', r'^django/polls/(?P<id>\d+)/',
'mysite.polls.views.delete'),
('GET,POST,PUT', r'^django/goods/view/(?P<id>\d+)',
'mysite.goods.views.show'), # don't care of method except DELETE
)
If method + URL did not match current request, then Django should
raise Http404 error - like file is not found.
I it's clear, simple as possible and highly configurable. Also, we
have no magic here (no HTTP_method_name <-> view_method_name
dependencies).
You can always move method distinction to other file to keep urls.py
definitely clear:
urlpatterns = patterns('',
('*', r'^django/goods/', include('mysite.goods.urls')),
)
P.S. We can move methods into constants like that:
from django.http.methods import *
urlpatterns = patterns('',
(HTTP_ALL, r'^django/admin/',
include('django.contrib.admin.urls')),
(HTTP_GET, r'^django/polls/(?P<id>\d+)/',
'mysite.polls.views.show'),
)
That makes it even easier.
On a more objective note, though, would that mean that every
urlpattern would require an HTTP method, or could it be ignored (with
GET presumably implied)? If it can be ignored, how would the resolver
tell the difference between an HTTP method string and a URL regex
string? (I think I have an answer for this, but it's worth asking
anyway.)
And if the method is in fact required in all cases, I think this would
add way too much added complexity for the common case. Most people
only use GET and POST, and most of their URLs are going to be GET
only. On top of that, I expect most GET/POST views are forms, where it
would make sense to share logic for form generation, template
selection, etc. Expecting people to separate those into two separate
views seems unnecessarily complex.
And yes, I do realize that your constants proposal does alleviate some
of these problems. For instance, you mention having HTTP_ALL, which,
if used as a default, would provide existing functionality without
change. Also, by using constants, the values could be numbers, which
could then be OR'd together (ie, HTTP_GET | HTTP_POST), and this would
also provide a means of differentiating between the required HTTP
method(s) and the regex string. These things do help somewhat, but
they add a great deal of complexity where I don't think it's merited.
That said, I think there are probably others out there like you who
would want this, and there's actually nothing stopping you from
releasing it as a separate app, or even a snippet. Essentially, you'd
just write a replacement for the existing url resolvers, probably
subclassing the existing ones to minimize new code. Then in your
urls.py, you import your own rather than the Django ones. If nothing
else, this would give the core developers proof of what you're talking
about, it would give other developers a chance to try it out and see
if they like it any better, it would give you some valuable feedback
on the proposal in case it needs tweaking, and it would give you a
chance to get your feet wet on hacking a bit on things related to
Django internals.
If you'd like to go that route, let me know and I'd be willing to help
you out with it.
-Gul
Well, looks like I misspoke. It seems the URL resolver is only given
the path, as opposed to the whole request object, so it would require
a bit more hacking than I originally thought. It might still be
possible without changing any Django internals, but you'd have to
touch more than you should, and it wouldn't be pretty. I wouldn't
recommend it, so consider that whole idea withdrawn. Sorry about not
looking at the code before I typed.
-Gul
However, using the new-ish urlpattern url() notation would be the go
here. Just bung a new kwarg on url.__init__() with a default of
something like None, ALL or *, that would optionally accept values
like GET, POST, HEAD, etc.
On Oct 2, 10:53 pm, "Marty Alchin" <gulop...@gamemusic.org> wrote:
Note that you'd have to consider how reversing the urls should work
also -- would you have to specify the method when reversing,
defaulting to GET?
Andrew
Examples:
{# typical usage: #}
<a href='{% url mysite.goods_management.views.list %}'>Goods</a>
{# exclusive usage, many routes to the same view: #}
<a href='{% url mysite.goods_management.views.food 'GET' %}'>List
food</a>
Or we can even create separate functions for each method:
<a href='{% url_get mysite.goods_management.views.food %}'>List
food</a>
<form action='{% url_post mysite.goods_management.views.food %}'
method='post'>
<input type='submit' value='Update food' />
</form>
Or just make people use named URLs, which is already the solution for
multiple routes to the same view :)
--
Collin Grady
When a person goes on a diet, the first thing he loses is his temper.