django-easyurls: Making it easier to read and write Django URLs

By making assumptions, like year is usually a 4-digit number and id 1 or more digits, django-easyurls takes much of the repetition out of defining URLs, using a syntax that's shorter and easier to read.

Compare the following:

# standard
urlpatterns += patterns('django.views.generic.date_based',
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/(?P<slug>[-\w]+)/$',
        'object_detail', info_dict),
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\d{1,2})/$',
        'archive_day',   info_dict),
    url(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict),
    url(r'^(?P<year>\d{4})/$', 'archive_year',  info_dict),
)

# use easyurls, and let it generate the regex for you
from easyurls import regex as p
urlpatterns += patterns('django.views.generic.date_based',
    url(p('<year>/<month:mon>/<day>/<slug>'), 'object_detail', info_dict),
    url(p('<year>/<month:mon>/<day>'),        'archive_day',   info_dict),
    url(p('<year>/<month:mon>'),              'archive_month', info_dict),
    url(p('<year>'),                          'archive_year',  info_dict),
)

These two sets of URL patterns are functionally equivalent -- the same regex is passed to url() in both cases, but the second is shorter and clearer. Why keep repeating that year is a 4-digit number, month is 3 letters, and day a 1 or 2 digit number? Also, since 99% of the time one wants the pattern to start with '^', and end with '/$', why keep repeating it? If you don't want them, you can say so.

django-easyurls works by defining names for patterns and generating regular expressions for you. By default, the name of the captured variable is the name of the pattern. This can be overriden, as is done above where the "mon" pattern is used for "month", instead of the default \d{1,2}.

Here's a list of the default patterns:

>>> from easyurls import regex as p
>>> for name in sorted(p.patterns):
...     print '%5s: %s' % (name,p.patterns[name])
  day: \d{1,2}
   id: \d+
  mon: [a-z]{3}
month: \d{1,2}
    n: \d+
 slug: [\w-]+
  tag: \w+
 year: \d{4}

To use a different name for a pattern, or different pattern for a name, add the pattern after the name, prefixing the pattern with ":".

# default for month is \d{1,2}
>>> print p('<month>')
^(?P<month>\d{1,2})/$

# using [a-z]{3} for month
>>> print p('<month:mon>')
^(?P<month>[a-z]{3})/$

# using [a-z]{3} for mmm
>>> print p('<mmm:mon>')
^(?P<mmm>[a-z]{3})/$

It's easy to add new or override existing patterns:

>>> p['yy'] = r'\d{2}'
>>> p['mm'] = r'\d{2}'
>>> p['dd'] = r'\d{2}'

>>> print p('<year:yy>/<month:mm>/<day:dd>')
^(?P<year>\d{2})/(?P<month>\d{2})/(?P<day>\d{2})/$

By default, if no pattern is found, \d+ is assumed.

>>> print p('releases/<project_id>')
^releases/(?P<project_id>\d+)/$

For flexibility, you can always use a regular expression.

# regex for unknown "zip_code"
>>> print p('zip/<zip_code:\d{5}>')
^zip/(?P<zip_code>\d{5})/$

# override slug, allowing "."
>>> print p('<slug:[\w-.]+>')
^(?P<slug>[\w-.]+)/$

For demonstration, and testing, purposes here's how prepending and appending or '^', '/', and '$' is handled:

>>> print p('')
^$
>>> print p('foo$')
^foo$
>>> print p('foo/')
^foo/$
>>> print p('/')
^/$

Prepending of '^' and appending of '/' and '$' can be disabled.

>>> p('foo', anchor=False, terminate=False, append_slash=False)
'foo'

Getting django-easyurls

django-easyurls lives in a mercurial repository on Bitbucket, available here: http://bitbucket.org/orutherfurd/django-easyurls/. Alternatively, you can download the single file easyurls.py, which is all you really need.

Tagged with: annoucement django

posted on the March 23rd, 2009 at 2:23 p.m.

Breads to Bake

Scali from Bread cetera. SteveB often has good videos, too.

Flaxseed Rye, based on Hamelman's "Flaxseed Bread". As always, Susan's pictures are enticing!

While on the topic of ryes, I've recently done a couple of Hamelman's: "70 Percent Rye with a Rye Soaker and Whole-Wheat Flour" and "Volkornbrot with Flaxseeds" -- both of which were about as serious as they sound, but very good. Angus was particularly fond of the of the Volkornbrot, always requesting a piece to go along with his usual breakfast.

Tagged with: bread

posted on the March 19th, 2009 at 1:11 p.m.

Flatbread Recipes to Try

Some flatbread recipes to try. I'm still very much in search of a great flour tortilla recipe. The one I use from Crust and Crumb is good, but not great. I've stumbled across several recipes that say lard is the key.

Tagged with: bread

posted on the March 15th, 2009 at 12:06 p.m.

Released FirstMate 0.3.1 plugin for jEdit

  • Released FirstMate 0.3.1 plugin for jEdit. Fixes 2 bugs related to apostrophe handling for auto-paired characters.

Tagged with: firstmate announcement jedit

posted on the June 23rd, 2008

New Vimposter Releases

Tagged with: announcement vimposter jedit

posted on the December 8th, 2007

Added Links Section

Tagged with: announcement

posted on the November 25th, 2007

This Site is Now Powered By Django

  • This site is now powered by Django.

Tagged with: announcement

posted on the September 3rd, 2007

jEdit Plugin Releases and New and Updated jEdit Modes

Released Tags 2.0.2 plugin for jEdit

  • Released Tags 2.0.2 plugin for jEdit. Updated for 4.3pre3.
  • Released MoinMoin 0.3.4 plugin for jEdit. Updated for MoinMoin 1.5.

Tagged with: moinmoin announcement jedit tags

posted on the April 14th, 2006

New Version of MoinMoin Plugin for jEdit

Tagged with: moinmoin announcement jedit

posted on the March 16th, 2006

Django Edit Mode for jEdit

Tagged with: announcement jedit

posted on the August 12th, 2005

New Vimposter Release

  • Updated Vimposter plugin to work with (and require) jEdit 4.3pre3 (not yet released). I probably won't do a new release until 4.3pre3 is released, unless I get requests, but the code's in the repository.
  • New build of new jEdit Launcher. Includes a GUI for editing settings, instead of having to edit the registry directly.

Tagged with: announcement vimposter jedit

posted on the July 20th, 2005

New EditorScheme Release and Build of New jEdit Launcher

  • New build of new jEdit Launcher, with better logging of errors and handling of missing 'Working directory setting'.
  • EditorScheme plugin 1.0, 'DarkMine' scheme from Matt Gilbert.

Tagged with: announcement jedit editorscheme

posted on the May 3rd, 2005

jEdit Macro Updates

Tagged with: announcement jedit

posted on the April 14th, 2005

Vimposter 0.0.7 Released

Tagged with: announcement vimposter jedit

posted on the April 12th, 2005