Opened 11 years ago
Closed 11 years ago
#20479 closed New feature (wontfix)
Adding the concept predicates in the Django url routing
Reported by: | rach | Owned by: | nobody |
---|---|---|---|
Component: | Core (URLs) | Version: | dev |
Severity: | Normal | Keywords: | urlresolver, predicates |
Cc: | marc.tamlyn@… | Triage Stage: | Someday/Maybe |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It's something that I tried to bring back from Pyramid.
It's not as complete because the url routing and view lookup is made in one step in django.
But that allow to add simple matching rules in the logic of the UrlResolver
See pull-request : https://github.com/django/django/pull/1199
It includes Code, Doc, Tests.
The motivation behind this feature is being able to have more flexibility in the way to organize
function based views. And specially getting rid of redundant test.
Use cases:
- Post multi forms on a single views, this allow to match the view which match when a specific submit is in the request
- Get rid of redundant
if method == 'POST'
in function base view
Code highlighting:
url_pattern += url('/', my_view_GET) url_pattern += url('/', my_view_POST) #Decorator to make a urls match only if the predicates return True predicate_GET = lambda request: request.method == 'GET' predicate_POST = lambda request: request.method == 'POST' @url_predicates([predicate_GET]) def my_view_GET(request): # I can assume now that only GET requests get match to the url # associated to this view # ... @url_predicates([predicate_POST]) def my_view_POST(request): # I can assume now that only POST requests get match to the url # associated to this view # ...
....
The implementation is probably imperfect let me know your feedbacks.
But I hope that could end with a more flexible and powerful routing in Django.
The Pyramid documentation illustrate very well the configuration possibility of predicates :
http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/viewconfig.html#predicate-arguments
Change History (4)
comment:1 by , 11 years ago
comment:2 by , 11 years ago
Cc: | added |
---|---|
Has patch: | set |
Triage Stage: | Unreviewed → Someday/Maybe |
This seems to me to be another example of "doing different things at the same url". There are multiple ways to approach this in Django, and no obvious "correct" answer. Examples:
- Proposed
ViewCollection
in #16213 - Implemented
ViewSet
from DjangoRestFramework ContinueResolving
from https://github.com/jacobian/django-multiurl- A simple wrapper "view" function which checks the predicates you spoke about and routes to other functional views appropriately
At the moment it's not clear what the best approach is. In particular, I don't like this implementation, but I'd like to know more example use cases of what you're trying to achieve. For splitting by HTTP method the basic View
class is already very good at this. For more complex functionality such as handling multiple forms etc this is currently not so well determined (especially in the generic views space).
comment:3 by , 11 years ago
There is probably a better way to implement it and it's more in implementation to illustrate the concept to unloose the relationship between url routing and view lookup which are only one thing at this stage in Django.
I m not fan of django-multiurl approach as it add one level of complexity at the url configuration level, but I agree that could be implemented following the same technique and wrap the urls into a container. I may implement it for my next django project.
The usecases are numerous:
- Organize function base view to treat XHR request
- MultiForm submit on a same url
- Build easily api from function base view to handle PUT/POST/GET/DELETE
- create reusable condition to check url arguments without having to write crazy regexp
- Call specific function base view base contentType
- Not getting a MethodNotAllowed when it's not what you want
- Call a specific view matter if the user is login or not ( ex: / -> welcom or home)
...
More generics:
- Organize code from function base view and get rid off redundant logic
- Extending function base view without having to follow the Class Base view model
comment:4 by , 11 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
I agree with Marc that this particular implementation won't work for Django. I do think it would be useful to mention the features of HTTP method dispatching of the View class somewhere in the URLconf docs, and more generally crystallize the philosophy of Django's core URL mapping, with some general discussions or links to extend or wrap the logic.
Your given example of method predicates is already present in Django and can be done with the following decorators:
django.views.decorators.http.require_http_methods
django.views.decorators.http.require_GET
django.views.decorators.http.require_POST
django.views.decorators.http.require_safe
Note that these only consider the value of
request.method
. I think the request methods are quite a common use case but it may be worth making this more general (i.e., predicates onrequest
).