5
A clean, elegant URL scheme is an important detail in a high-quality Web
6
application. Django lets you design URLs however you want, with no framework
9
There's no ``.php`` or ``.cgi`` required, and certainly none of that
10
``0,2097,1-1-1928,00`` nonsense.
12
See `Cool URIs don't change`_, by World Wide Web creator Tim Berners-Lee, for
13
excellent arguments on why URLs should be clean and usable.
15
.. _Cool URIs don't change: http://www.w3.org/Provider/Style/URI
20
To design URLs for an app, you create a Python module informally called a
21
**URLconf** (URL configuration). This module is pure Python code and
22
is a simple mapping between URL patterns (as simple regular expressions) to
23
Python callback functions (your views).
25
This mapping can be as short or as long as needed. It can reference other
26
mappings. And, because it's pure Python code, it can be constructed
29
How Django processes a request
30
==============================
32
When a user requests a page from your Django-powered site, this is the
33
algorithm the system follows to determine which Python code to execute:
35
1. Django looks at the ``ROOT_URLCONF`` setting in your `settings file`_.
36
This should be a string representing the full Python import path to your
37
URLconf. For example: ``"mydjangoapps.urls"``.
38
2. Django loads that Python module and looks for the variable
39
``urlpatterns``. This should be a Python list, in the format returned by
40
the function ``django.conf.urls.defaults.patterns()``.
41
3. Django runs through each URL pattern, in order, and stops at the first
42
one that matches the requested URL.
43
4. Once one of the regexes matches, Django imports and calls the given
44
view, which is a simple Python function. The view gets passed a
45
`request object`_ as its first argument and any values captured in the
46
regex as remaining arguments.
48
.. _settings file: ../settings/
49
.. _request object: ../request_response/#httprequest-objects
54
Here's a sample URLconf::
56
from django.conf.urls.defaults import *
58
urlpatterns = patterns('',
59
(r'^articles/2003/$', 'news.views.special_case_2003'),
60
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
61
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
62
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
67
* ``from django.conf.urls.defaults import *`` makes the ``patterns()``
70
* To capture a value from the URL, just put parenthesis around it.
72
* There's no need to add a leading slash, because every URL has that. For
73
example, it's ``^articles``, not ``^/articles``.
75
* The ``'r'`` in front of each regular expression string is optional but
76
recommended. It tells Python that a string is "raw" -- that nothing in
77
the string should be escaped. See `Dive Into Python's explanation`_.
81
* A request to ``/articles/2005/03/`` would match the third entry in the
82
list. Django would call the function
83
``news.views.month_archive(request, '2005', '03')``.
85
* ``/articles/2005/3/`` would not match any URL patterns, because the
86
third entry in the list requires two digits for the month.
88
* ``/articles/2003/`` would match the first pattern in the list, not the
89
second one, because the patterns are tested in order, and the first one
90
is the first test to pass. Feel free to exploit the ordering to insert
91
special cases like this.
93
* ``/articles/2003`` would not match any of these patterns, because each
94
pattern requires that the URL end with a slash.
96
* ``/articles/2003/03/3/`` would match the final pattern. Django would call
97
the function ``news.views.article_detail(request, '2003', '03', '3')``.
99
.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3
104
The above example used simple, *non-named* regular-expression groups (via
105
parenthesis) to capture bits of the URL and pass them as *positional* arguments
106
to a view. In more advanced usage, it's possible to use *named*
107
regular-expression groups to capture URL bits and pass them as *keyword*
110
In Python regular expressions, the syntax for named regular-expression groups
111
is ``(?P<name>pattern)``, where ``name`` is the name of the group and
112
``pattern`` is some pattern to match.
114
Here's the above example URLconf, rewritten to use named groups::
116
urlpatterns = patterns('',
117
(r'^articles/2003/$', 'news.views.special_case_2003'),
118
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
119
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'),
120
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'),
123
This accomplishes exactly the same thing as the previous example, with one
124
subtle difference: The captured values are passed to view functions as keyword
125
arguments rather than positional arguments. For example:
127
* A request to ``/articles/2005/03/`` would call the function
128
``news.views.month_archive(request, year='2005', month='03')``, instead
129
of ``news.views.month_archive(request, '2005', '03')``.
131
* A request to ``/articles/2003/03/3/`` would call the function
132
``news.views.article_detail(request, year='2003', month='03', day='3')``.
134
In practice, this means your URLconfs are slightly more explicit and less prone
135
to argument-order bugs -- and you can reorder the arguments in your views'
136
function definitions. Of course, these benefits come at the cost of brevity;
137
some developers find the named-group syntax ugly and too verbose.
139
The matching/grouping algorithm
140
-------------------------------
142
Here's the algorithm the URLconf parser follows, with respect to named groups
143
vs. non-named groups in a regular expression:
145
If there are any named arguments, it will use those, ignoring non-named arguments.
146
Otherwise, it will pass all non-named arguments as positional arguments.
148
In both cases, it will pass any extra keyword arguments as keyword arguments.
149
See "Passing extra options to view functions" below.
151
What the URLconf searches against
152
=================================
154
The URLconf searches against the requested URL, as a normal Python string. This
155
does not include GET or POST parameters, or the domain name.
157
For example, in a request to ``http://www.example.com/myapp/``, the URLconf
158
will look for ``/myapp/``.
160
In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look
163
The URLconf doesn't look at the request method. In other words, all request
164
methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same
165
function for the same URL.
167
Syntax of the urlpatterns variable
168
==================================
170
``urlpatterns`` should be a Python list, in the format returned by the function
171
``django.conf.urls.defaults.patterns()``. Always use ``patterns()`` to create
172
the ``urlpatterns`` variable.
174
Convention is to use ``from django.conf.urls.defaults import *`` at the top of
175
your URLconf. This gives your module access to these objects:
180
A function that takes a prefix, and an arbitrary number of URL patterns, and
181
returns a list of URL patterns in the format Django needs.
183
The first argument to ``patterns()`` is a string ``prefix``. See
184
"The view prefix" below.
186
The remaining arguments should be tuples in this format::
188
(regular expression, Python callback function [, optional dictionary])
190
...where ``optional dictionary`` is optional. (See
191
_`Passing extra options to view functions` below.)
196
A string representing the full Python import path to the view that should be
197
called if none of the URL patterns match.
199
By default, this is ``'django.views.defaults.page_not_found'``. That default
200
value should suffice.
205
A string representing the full Python import path to the view that should be
206
called in case of server errors. Server errors happen when you have runtime
209
By default, this is ``'django.views.defaults.server_error'``. That default
210
value should suffice.
215
A function that takes a full Python import path to another URLconf that should
216
be "included" in this place. See _`Including other URLconfs` below.
218
Notes on capturing text in URLs
219
===============================
221
Each captured argument is sent to the view as a plain Python string, regardless
222
of what sort of match the regular expression makes. For example, in this
225
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
227
...the ``year`` argument to ``news.views.year_archive()`` will be a string, not
228
an integer, even though the ``\d{4}`` will only match integer strings.
230
A convenient trick is to specify default parameters for your views' arguments.
231
Here's an example URLconf and view::
234
urlpatterns = patterns('',
235
(r'^blog/$', 'blog.views.page'),
236
(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
239
# View (in blog/views.py)
240
def page(request, num="1"):
241
# Output the appropriate page of blog entries, according to num.
243
In the above example, both URL patterns point to the same view --
244
``blog.views.page`` -- but the first pattern doesn't capture anything from the
245
URL. If the first pattern matches, the ``page()`` function will use its
246
default argument for ``num``, ``"1"``. If the second pattern matches,
247
``page()`` will use whatever ``num`` value was captured by the regex.
252
Each regular expression in a ``urlpatterns`` is compiled the first time it's
253
accessed. This makes the system blazingly fast.
258
You can specify a common prefix in your ``patterns()`` call, to cut down on
261
Here's the example URLconf from the `Django overview`_::
263
from django.conf.urls.defaults import *
265
urlpatterns = patterns('',
266
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
267
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
268
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'),
271
In this example, each view has a common prefix -- ``'mysite.news.views'``.
272
Instead of typing that out for each entry in ``urlpatterns``, you can use the
273
first argument to the ``patterns()`` function to specify a prefix to apply to
276
With this in mind, the above example can be written more concisely as::
278
from django.conf.urls.defaults import *
280
urlpatterns = patterns('mysite.news.views',
281
(r'^articles/(\d{4})/$', 'year_archive'),
282
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
283
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
286
Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
287
that in automatically.
289
.. _Django overview: ../overview/
291
Multiple view prefixes
292
----------------------
294
In practice, you'll probably end up mixing and matching views to the point
295
where the views in your ``urlpatterns`` won't have a common prefix. However,
296
you can still take advantage of the view prefix shortcut to remove duplication.
297
Just add multiple ``patterns()`` objects together, like this:
301
from django.conf.urls.defaults import *
303
urlpatterns = patterns('',
304
(r'^/?$', 'django.views.generic.date_based.archive_index'),
305
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'),
306
(r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'),
311
from django.conf.urls.defaults import *
313
urlpatterns = patterns('django.views.generic.date_based',
314
(r'^/?$', 'archive_index'),
315
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'),
318
urlpatterns += patterns('weblog.views',
319
(r'^tag/(?P<tag>\w+)/$', 'tag'),
322
Including other URLconfs
323
========================
325
At any point, your ``urlpatterns`` can "include" other URLconf modules. This
326
essentially "roots" a set of URLs below other ones.
328
For example, here's the URLconf for the `Django website`_ itself. It includes a
329
number of other URLconfs::
331
from django.conf.urls.defaults import *
333
urlpatterns = patterns('',
334
(r'^weblog/', include('django_website.apps.blog.urls.blog')),
335
(r'^documentation/', include('django_website.apps.docs.urls.docs')),
336
(r'^comments/', include('django.contrib.comments.urls.comments')),
339
Note that the regular expressions in this example don't have a ``$``
340
(end-of-string match character) but do include a trailing slash. Whenever
341
Django encounters ``include()``, it chops off whatever part of the URL matched
342
up to that point and sends the remaining string to the included URLconf for
345
.. _`Django website`: http://www.djangoproject.com/
350
An included URLconf receives any captured parameters from parent URLconfs, so
351
the following example is valid::
353
# In settings/urls/main.py
354
urlpatterns = patterns('',
355
(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
358
# In foo/urls/blog.py
359
urlpatterns = patterns('foo.views',
360
(r'^$', 'blog.index'),
361
(r'^archive/$', 'blog.archive'),
364
In the above example, the captured ``"username"`` variable is passed to the
365
included URLconf, as expected.
367
Passing extra options to view functions
368
=======================================
370
URLconfs have a hook that lets you pass extra arguments to your view functions,
371
as a Python dictionary.
373
Any URLconf tuple can have an optional third element, which should be a
374
dictionary of extra keyword arguments to pass to the view function.
378
urlpatterns = patterns('blog.views',
379
(r'^/blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),
382
In this example, for a request to ``/blog/2005/``, Django will call the
383
``blog.views.year_archive()`` view, passing it these keyword arguments::
385
year='2005', foo='bar'
387
This technique is used in `generic views`_ and in the `syndication framework`_
388
to pass metadata and options to views.
390
.. _generic views: ../generic_views/
391
.. _syndication framework: ../syndication/
393
.. admonition:: Dealing with conflicts
395
It's possible to have a URL pattern which captures named keyword arguments,
396
and also passes arguments with the same names in its dictionary of extra
397
arguments. When this happens, the arguments in the dictionary will be used
398
instead of the arguments captured in the URL.
400
Passing extra options to ``include()``
401
--------------------------------------
403
Similarly, you can pass extra options to ``include()``. When you pass extra
404
options to ``include()``, *each* line in the included URLconf will be passed
407
For example, these two URLconf sets are functionally identical:
412
urlpatterns = patterns('',
413
(r'^blog/', include('inner'), {'blogid': 3}),
417
urlpatterns = patterns('',
418
(r'^archive/$', 'mysite.views.archive'),
419
(r'^about/$', 'mysite.views.about'),
425
urlpatterns = patterns('',
426
(r'^blog/', include('inner')),
430
urlpatterns = patterns('',
431
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
432
(r'^about/$', 'mysite.views.about', {'blogid': 3}),
435
Note that extra options will *always* be passed to *every* line in the included
436
URLconf, regardless of whether the line's view actually accepts those options
437
as valid. For this reason, this technique is only useful if you're certain that
438
every view in the the included URLconf accepts the extra options you're passing.
440
Passing callable objects instead of strings
441
===========================================
443
Some developers find it more natural to pass the actual Python function object
444
rather than a string containing the path to its module. This alternative is
445
supported -- you can pass any callable object as the view.
447
For example, given this URLconf in "string" notation::
449
urlpatterns = patterns('',
450
(r'^archive/$', 'mysite.views.archive'),
451
(r'^about/$', 'mysite.views.about'),
452
(r'^contact/$', 'mysite.views.contact'),
455
You can accomplish the same thing by passing objects rather than strings. Just
456
be sure to import the objects::
458
from mysite.views import archive, about, contact
460
urlpatterns = patterns('',
461
(r'^archive/$', archive),
462
(r'^about/$', about),
463
(r'^contact/$', contact),
466
The following example is functionally identical. It's just a bit more compact
467
because it imports the module that contains the views, rather than importing
468
each view individually::
470
from mysite import views
472
urlpatterns = patterns('',
473
(r'^archive/$', views.archive),
474
(r'^about/$', views.about),
475
(r'^contact/$', views.contact),
478
The style you use is up to you.
480
Note that if you use this technique -- passing objects rather than strings --
481
the view prefix (as explained in "The view prefix" above) will have no effect.