Proposal for 1.2: Improved URL system

9 views
Skip to first unread message

Leaf

unread,
Oct 17, 2009, 11:29:08 AM10/17/09
to Django developers
Currently, Django uses URLs based on regular expressions. I think that
is a suboptimal way to go about things because:

- Regular expressions are ugly and can be difficult to write.
- Regular expressions don't provide an easy way to match certain types
of fields, like slugs or month names.
- Regular expressions are difficult to reverse. (According to the
docs, regular expressions using a | to separate multiple possibilities
are irreversible.)

My proposal is to add a URL resolution system on top of the current
one [for backwards compatibility] that works in a similar way to
Werkzeug's URL resolver. You express URL patterns in a syntax like '/
<slug:slug>/' (where the first 'slug' is a converter and the second
'slug' is the name to be passed), which is then converted into a
regular expression to match URLs ('/(?P<slug>[A-Za-z0-9_-]+)/'), and a
format string ('/%(slug)s/'). When resolving, the regular expression
is matched against the URL, and when reversing, the variables are
validated and then substituted into the format string. There would
probably be converters for 'string', 'slug', 'number', 'monthname',
etc. The advantages of this system are:

- It makes the URL patterns cleaner and easier to write in the
URLconf.
- It improves the accuracy of reversing, because you don't have to
scan a regex to find out what to reverse.
- It can be made backwards-compatible with the old system, possibly by
using a 'Pattern()' function/class to generate a new-style pattern and
having the 'patterns()' function use the current behavior for tuples
or RegexURLPattern instances.

Sorry to propose this right up against the voting deadline for 1.2
features, but it's one of the things that has always bugged me about
Django and I would really like to see this in 1.2.

-- LeafStorm

James Bennett

unread,
Oct 17, 2009, 7:00:14 PM10/17/09
to django-d...@googlegroups.com
On Sat, Oct 17, 2009 at 10:29 AM, Leaf <leafst...@gmail.com> wrote:
> Sorry to propose this right up against the voting deadline for 1.2
> features, but it's one of the things that has always bugged me about
> Django and I would really like to see this in 1.2.

-1.

Replacing regular expressions with... well, what looks like regular
expressions with names doesn't make much sense, and even if it did
we're not going to change a major component like this in the middle of
a stable release line.


--
"Bureaucrat Conrad, you are technically correct -- the best kind of correct."

Leaf

unread,
Oct 17, 2009, 9:27:35 PM10/17/09
to Django developers
Okay, I guess I can live with that. Maybe, if I can write a patch
implementing this in a completely backwards-compatible way, I'll
propose it again for a later version (earlier in the release cycle).

Though I disagree with your characterization of it as "what looks like
regular expressions with names." It would be compiled down to regular
expressions, yes, but it's not really intended to be just a wrapper
over regular expressions. (I wrote one of those in about three
minutes.) Maybe if you looked at Werkzeug's routing source code, you'd
see what I mean. I personally like it because it's cleaner, both using
it from the front end and in the source.

-- LeafStorm

On Oct 17, 7:00 pm, James Bennett <ubernost...@gmail.com> wrote:

Ned Batchelder

unread,
Oct 17, 2009, 9:47:38 PM10/17/09
to django-d...@googlegroups.com
This seems to me to be a perfect candidate for implementation outside of core.  Write a facility that takes your simpler url patterns, and creates standard Django urlpatterns from them.  Publish it.  If it catches on, then we can discuss what future version of Django might include it as core.

BTW: I've also thought that regular expressions are great for their power, but generally overkill for url patterns.

--Ned.

Jannis Leidel

unread,
Oct 18, 2009, 6:52:00 AM10/18/09
to django-d...@googlegroups.com
Hi LeafStorm,

> Okay, I guess I can live with that. Maybe, if I can write a patch
> implementing this in a completely backwards-compatible way, I'll
> propose it again for a later version (earlier in the release cycle).

In the meantime you might want to have a look at Surlex, Cody
Soyland's 3rd party app that does pretty much what you propose: http://codysoyland.com/blog/2009/sep/6/introduction-surlex/
.

Best,
Janis

Maxim Penzin

unread,
Oct 17, 2009, 11:24:39 PM10/17/09
to django-d...@googlegroups.com
> My proposal is to add a URL resolution system on top of the current
> one [for backwards compatibility] that works in a similar way to
> Werkzeug's URL resolver. You express URL patterns in a syntax like '/
> <slug:slug>/' (where the first 'slug' is a converter and the second
> 'slug' is the name to be passed), which is then converted into a
> regular expression to match URLs ('/(?P<slug>[A-Za-z0-9_-]+)/'), and a
> format string ('/%(slug)s/'). When resolving, the regular expression
> is matched against the URL, and when reversing, the variables are
> validated and then substituted into the format string. There would
> probably be converters for 'string', 'slug', 'number', 'monthname',
> etc. The advantages of this system are:

'pythonic' %(slug)s syntax is a good idea.
Regexes are very flexible but we don't need it in most cases.

Another crazy idea for shorter object fetch is
"/%(model_name.id)d/" or may be another syntax like "/%%(model_name)/"
to get rid of
get_object_or_404( id=int(id) )
at the first line of every view method.


--
-- mpe...@gmail.com icq:3861496 www.penzin.ru --

Dougal Matthews

unread,
Oct 18, 2009, 10:17:08 AM10/18/09
to django-d...@googlegroups.com
2009/10/18 Maxim Penzin <mpe...@gmail.com>

Another crazy idea for shorter object fetch is
"/%(model_name.id)d/" or may be another syntax like "/%%(model_name)/"
to get rid of
 get_object_or_404( id=int(id) )
at the first line of every view method.
 

I quite like this idea, not sure about that syntax exactly but the idea is nice. Personally I'm a fan of regular expressions so wouldn't want to see them removed or abstracted to a level that really isn't that different.

Something like this however would be more interesting as as you say it skips a bit of code that ends up in many views. It could also be used pass the view pre-filtered querysets. Say  for example with date based filters. i.e. /2009/, /2009/09/ and /2009/09/09/ would go to the same view but rather than pass the date or date parts the view is passed the result of a Model.objects.filter()

However, I'm at a total loss of how the syntax for this would work :)

oruth...@gmail.com

unread,
Oct 18, 2009, 11:34:20 AM10/18/09
to Django developers
Hi LeafStorm,
I also did something like this. You can find it here:

http://bitbucket.org/orutherfurd/django-easyurls/

docs and examples start here:

http://bitbucket.org/orutherfurd/django-easyurls/src/tip/easyurls.py#cl-30

-Ollie

dchandek

unread,
Oct 19, 2009, 10:14:13 AM10/19/09
to Django developers
-1. I would question the wisdom of introducing a second URL system on
the basis of simplicity and clarity alone. The assertion that regular
expressions are "ugly" and "difficult" is, I suppose, subjective. I
prefer to think of them as "powerful". In any case, I think we should
ask whether the benefit of providing an alternative syntax that's
"easier" and purports to solve some current issues is in the long run
worth the cost supporting two systems.

--David
Reply all
Reply to author
Forward
0 new messages