Opened 2 years ago

Closed 2 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: master
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 Changed 2 years ago by svisser

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 on request).

comment:2 Changed 2 years ago by mjtamlyn

  • Cc marc.tamlyn@… added
  • Has patch set
  • Triage Stage changed from Unreviewed to 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 Changed 2 years ago by rach

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 Changed 2 years ago by ptone

  • Resolution set to wontfix
  • Status changed from new to 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.

Note: See TracTickets for help on using tickets.
Back to Top