Predicate as suggested new feature to extend url resolver process

72 views
Skip to first unread message

Rach Belaid

unread,
May 22, 2013, 12:05:59 PM5/22/13
to Django developers
I just did a pull request resulting of my last Django sprints for
adding a new feature in Django.

https://code.djangoproject.com/ticket/20479

The idea is being able to have more control on the url resolving
process.

I have no merit behind the idea of predicate. Predicate is one of my
favorite feature in Pyramid/Pylons to allow more complex and flexible
routing.

I will be curious about feebacks? Do you like this idea of features ?

The implementation is probably imperfect so don't be too harsh ;) we
can always fix the implementation.

For people unaware about what is a predicate, I advice to check the
pyramid doc here:
http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/viewconfig.html#predicate-arguments

Jacob Kaplan-Moss

unread,
May 22, 2013, 5:37:02 PM5/22/13
to django-developers
I'm not sure I understand what you're proposing here. How is this
different from @require_GET, @require_POST, and friends?

Jacob
> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
> To post to this group, send email to django-d...@googlegroups.com.
> Visit this group at http://groups.google.com/group/django-developers?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Rach Belaid

unread,
May 22, 2013, 6:14:36 PM5/22/13
to Django developers
It's different in the way that the view url won't match and the url
resolving will continue,
where require_GET would raise a django.http.HttpResponseNotAllowed

** I had to change the UrlResolver a bit **

This allow to have same urls which pick the right view base on the
state/values of the request.

Better example:

You post two forms on the same url.

:: urls.py ::

urlpattern += ( url('^$',view_signin), url('^$',view_signup))

signin = lambda r : 'signin' in r.POST
signup = lambda r : 'signup' in r.POST

:: views.py ::

@url_predicates([signin,])
def view_signin(request):
....

@url_predicates([signup,])
def view_signup(request):
....

No matter of the order of the urls regexp in the urls.py the right
view will match.

I can imagine that view predicate can look a bit obscure with having
used them in an other frameworks.

I did some slides which cover this feature in Pyramid.. It should make
the things more clear
http://www.slideshare.net/rachbelaid/pyramid-views-20820325


On May 22, 10:37 pm, Jacob Kaplan-Moss <ja...@jacobian.org> wrote:
> I'm not sure I understand what you're proposing here. How is this
> different from @require_GET, @require_POST, and friends?
>
> Jacob
>
>
>
>
>
>
>
> On Wed, May 22, 2013 at 11:05 AM, Rach Belaid <rachid.bel...@gmail.com> wrote:
> > I just did a pull request resulting of my last Django sprints for
> > adding a new feature in Django.
>
> >https://code.djangoproject.com/ticket/20479
>
> > The idea is being able to have more control on the url resolving
> > process.
>
> > I have no merit behind the idea of predicate. Predicate is one of my
> > favorite feature in Pyramid/Pylons to allow more complex and flexible
> > routing.
>
> > I will be curious about feebacks? Do you like this idea of features ?
>
> > The implementation is probably imperfect so don't be too harsh ;) we
> > can always fix the implementation.
>
> > For people unaware about what is a predicate, I advice to check the
> > pyramid doc here:
> >http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/viewcon...

Sean Bleier

unread,
May 22, 2013, 6:21:33 PM5/22/13
to django-d...@googlegroups.com
I think what Rach is suggesting is different from @require_GET,
@require_POST, etc. The patch essentially makes a view invisible if
the predicate function returns False.

I'm not sure this would be good for inclusion to django, since you are
tying url resolution to application state . This could have negative
implications, especially for performance. On top of that, the same
functionality could be achieved by creating a function/class to route
the request further after django has initially routed the request.
This would be preferable because the performance hit would be isolated
to the resolved routing function/class.

Rach Belaid

unread,
May 22, 2013, 7:13:38 PM5/22/13
to django-d...@googlegroups.com
Thanks for the feedback.

I assume If it's not use then performance should be the same.
But I don't know if the single check for the presence of the attribute or not would affect much the performance.

The goal of this feature is offering a hook to allow people extend a bit the routing logic.
Which is more difficult with Django because routing and view lookup are the same thing.

@Sean , I understand your point about have a single view but I hope this could help people to organize
their function based views in a nice way in the same way that required_GET could be done inside the view.

Will be great if you take few min to look how this feature is used in other framework.

I'm personally not convince my implementation is the right one but I hope that could open the discussion
to have a more extensible routing in Django.

Jacob Kaplan-Moss

unread,
May 22, 2013, 11:22:08 PM5/22/13
to django-developers
Hi Rach --

Thanks for the clarification. I'd like to make three broader points.
They may not seem like they're directly addressing your proposal, but
stick with me, I promise this comes together to your specific proposal
at the end:

1. "But framework X does it like this" isn't a particularly good
argument for why *Django* should do something. Yes, it's important to
understand and follow what's going on in the greater web world, and
yes it's important to beg, borrow, and steal good ideas. But you have
to articulate why an idea is *good for Django*. After all, if we
wanted to be just like Framework X, we'd all just be using Framework
X. In many ways the high quality of our competitors actually frees us
up to be *more* skeptical of what we add to Django. We don't *need* to
be more like other frameworks because those other frameworks are
usually *great* -- if you like them, you should use them! We should be
focusing on doing the things we're good at. Let Django be Django.

2. One of the really high bars you have to clear when you propose new
things for Django is the bar of utility. It's not good enough to
demonstrate that something's a good idea. It's not good enough to
demonstrate that it solves your problem. It's not even good enough to
demonstrate that it solves some bigger problem. You have to
demonstrate that what you're proposing is so useful that a sizable
portion of people using Django would be excited by your new thing. One
of Django's real strengths is its stability, but the cost of that
strength is that we say "no" a lot.

3. Flexibility is a very important goal. Our philosophy of "sensible
defaults" doesn't mean that the default choice should be the only
choice! It means that we should provide a reasonable default for most
people, but then give people "escape hatches" when those defaults
don't quite work out.

So given these principles, let's look at your proposal again:

1. Much of your argument seems to come down to "Pyramid does it this
way." It does, and it's a good match… for Pyramid. You haven't
articulated why this is a good addition *for Django*, and I think
that's because it isn't. Django's @require_POST and friends are
simple, obvious, and easy to understand, whereas this predicate
business adds another layer of complexity. Further, it violates one of
the cardinal design points of the routing system, which is that all
the information you need to figure out routing should be in the routes
file. Pushing routing logic down into the views -- which is what your
proposal does -- violates this basic tenant of Django. That design is
pretty close to set in stone; you're going to need a very excellent
argument to change a design choice that's been in place for nearly a
decade now.

2. One of the ways you might win that argument would be by arguing
massive utility for a large segment of Django's user base. Again,
though, we already have this feature implemented in a more
"Django-esque" way, so I don't really buy that argument.

3. Ah, but there is something deeper here worth looking at. URL
routing is one of the *least* flexible parts of Django. It's possible
to customize routing (see https://github.com/jacobian/django-multiurl
for one example), but it's rather complicated and relies on a pretty
deep understanding of how routing works. That's bad; it should be
easier to add these sorts of things if you choose *without* needing to
add something new to Django.

So, let's bring it all together:

What you're proposing -- view predicates -- isn't going to happen.
You're welcome to keep tilting at this windmill, but the chances of
this making it into Django proper are essentially nil. However, if
you're willing to take a step back from your specific problem, there
*is* something worth looking at here: making routing, in general,
something that's easier to swap out. So the path forward for you, if
you're willing to rise to the challenge, involves figuring out how to
make routing more flexible to the point that what you want to
implement is doable as a trivial third-party package.

Jacob

Rach Belaid

unread,
May 23, 2013, 6:29:46 AM5/23/13
to Django developers
Hi Jacob,

I understand your points. Sorry if my initial post was not properly
fitted.
Thanks for taking the time to clarify this points.

I was maybe not clear enough or got lost in translation in my post/
ticket/pr.
but I tried to specify my intention in all of them:

"I'm personally not convince my implementation is the right one but I
hope
that could open the discussion to have a more extensible routing in
Django."


About 1. I'm aware that Django has a specific way of doing thing and
I'm sorry if it has been understood in the
way that Framework x does that or look better. Not my intention to
start a debat X better than Y ... it's just a tool at end of day.
I try to have a rational approach so I checked how people was already
solving this problem.
I was more referring to them as a doc reference because predicate is
not an easy concept to understand.

Personally, I wanted to open a discussion and I got it so I'm fine and
happy with any resulting solution.

Agreed that predicate is maybe (probably) not a way to go for Django.
But I tried initially to do that as a third party and I couldn't find
a way to
figure it out with having access to the request.
But probably because of my lack of understanding about how the url
routing works.

Based on the point 3 ?

Could we imagine being able to swapping via a settings the class used
for the UrlResolving Process.
For people being able to build their own in the same spirit of the
backends.

I'm glad to read "it should be
easier to add these sorts of things if you choose *without* needing to
add something new to Django."

Because that was my initial intention to offer a easy way to extend
the routing without
any understanding of how the url resolving process works.


Let me try an other approach to my proposition:
==============================================

Problem: The RegexURLResolver is too complex and monolithic for
people understanding or extending it. It comes with some issues:
It don't allow to be swapped (from what I'm aware) or don't provide
any hooks to help people to extend the logic.

Solution : ** Something **
--------

My Solution : Predicates
--------

To not come empty handed, I propose a solution based on the concept of
predicate that I have seen in other framework (sorry for that).
Why I'm bringing that from somewhere else. Because I was lazy and
didn't want to invent a new concept when this one was heavily
documented already.

Is predicate solve the problem?
-------------------------------

Yes but probably create others as @Sean highlighted. Touching the
RegexURLResolver is complex but writing a test function is easy.

signin = lambda r : 'signin' in r.POST
signup = lambda r : 'signup' in r.POST


Opinion:
--------

I'm not convince that predicate is the right implementation for django
and I'm sure that the core dev will come with a much better idea to
this current problem.

===End====


Thanks @Jacob @Sean for taking the time to answer me and giving
feedbacks.
I'll check how did with https://github.com/jacobian/django-multiurl
and try to can come with
a 3rd party solution.
> to customize routing (seehttps://github.com/jacobian/django-multiurl
> >> >>http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/viewcon...
>
> >> >> --
> >> >> You received this message because you are subscribed to the Google
> >> >> Groups "Django developers" group.
> >> >> To unsubscribe from this group and stop receiving emails from it, send
> >> >> an email to django-develop...@googlegroups.com.
> >> >> To post to this group, send email to django-d...@googlegroups.com.
> >> >> Visit this group at
> >> >>http://groups.google.com/group/django-developers?hl=en.
> >> >> For more options, visithttps://groups.google.com/groups/opt_out.
>
> >> > --
> >> > You received this message because you are subscribed to the Google
> >> > Groups "Django developers" group.
> >> > To unsubscribe from this group and stop receiving emails from it, send
> >> > an email to django-develop...@googlegroups.com.
> >> > To post to this group, send email to django-d...@googlegroups.com.
> >> > Visit this group at
> >> >http://groups.google.com/group/django-developers?hl=en.
> >> > For more options, visithttps://groups.google.com/groups/opt_out.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Django developers" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to django-develop...@googlegroups.com.
> > To post to this group, send email to django-d...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages