Django documentation

This document is for Django's SVN release, which can be significantly different from previous releases. Get old docs here: Django 1.0

URL dispatcher

A clean, elegant URL scheme is an important detail in a high-quality Web application. Django lets you design URLs however you want, with no framework limitations.

There’s no .php or .cgi required, and certainly none of that 0,2097,1-1-1928,00 nonsense.

See Cool URIs don’t change, by World Wide Web creator Tim Berners-Lee, for excellent arguments on why URLs should be clean and usable.


To design URLs for an app, you create a Python module informally called a URLconf (URL configuration). This module is pure Python code and is a simple mapping between URL patterns (as simple regular expressions) to Python callback functions (your views).

This mapping can be as short or as long as needed. It can reference other mappings. And, because it’s pure Python code, it can be constructed dynamically.

How Django processes a request

When a user requests a page from your Django-powered site, this is the algorithm the system follows to determine which Python code to execute:

  1. Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has an attribute called urlconf (set by middleware request processing), its value will be used in place of the ROOT_URLCONF setting.
  2. Django loads that Python module and looks for the variable urlpatterns. This should be a Python list, in the format returned by the function django.conf.urls.defaults.patterns().
  3. Django runs through each URL pattern, in order, and stops at the first one that matches the requested URL.
  4. Once one of the regexes matches, Django imports and calls the given view, which is a simple Python function. The view gets passed an HttpRequest as its first argument and any values captured in the regex as remaining arguments.


Here’s a sample URLconf:

from django.conf.urls.defaults import *

urlpatterns = patterns('',
    (r'^articles/2003/$', 'news.views.special_case_2003'),
    (r'^articles/(\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),


  • from django.conf.urls.defaults import * makes the patterns() function available.
  • To capture a value from the URL, just put parenthesis around it.
  • There's no need to add a leading slash, because every URL has that. For example, it's ^articles, not ^/articles.
  • The 'r' in front of each regular expression string is optional but recommended. It tells Python that a string is "raw" -- that nothing in the string should be escaped. See Dive Into Python's explanation.

Example requests:

  • A request to /articles/2005/03/ would match the third entry in the list. Django would call the function news.views.month_archive(request, '2005', '03').
  • /articles/2005/3/ would not match any URL patterns, because the third entry in the list requires two digits for the month.
  • /articles/2003/ would match the first pattern in the list, not the second one, because the patterns are tested in order, and the first one is the first test to pass. Feel free to exploit the ordering to insert special cases like this.
  • /articles/2003 would not match any of these patterns, because each pattern requires that the URL end with a slash.
  • /articles/2003/03/3/ would match the final pattern. Django would call the function news.views.article_detail(request, '2003', '03', '3').

Named groups

The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it's possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here's the above example URLconf, rewritten to use named groups:

urlpatterns = patterns('',
    (r'^articles/2003/$', 'news.views.special_case_2003'),
    (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
    (r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),

This accomplishes exactly the same thing as the previous example, with one subtle