| 1 |
============== |
|---|
| 2 |
URL dispatcher |
|---|
| 3 |
============== |
|---|
| 4 |
|
|---|
| 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 |
|---|
| 7 |
limitations. |
|---|
| 8 |
|
|---|
| 9 |
There's no ``.php`` or ``.cgi`` required, and certainly none of that |
|---|
| 10 |
``0,2097,1-1-1928,00`` nonsense. |
|---|
| 11 |
|
|---|
| 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. |
|---|
| 14 |
|
|---|
| 15 |
.. _Cool URIs don't change: http://www.w3.org/Provider/Style/URI |
|---|
| 16 |
|
|---|
| 17 |
Overview |
|---|
| 18 |
======== |
|---|
| 19 |
|
|---|
| 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). |
|---|
| 24 |
|
|---|
| 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 |
|---|
| 27 |
dynamically. |
|---|
| 28 |
|
|---|
| 29 |
How Django processes a request |
|---|
| 30 |
============================== |
|---|
| 31 |
|
|---|
| 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: |
|---|
| 34 |
|
|---|
| 35 |
1. Django determines the root URLconf module to use. Ordinarily, |
|---|
| 36 |
this is the value of the ``ROOT_URLCONF`` setting in your |
|---|
| 37 |
`settings file`_, but if the incoming ``HttpRequest`` object |
|---|
| 38 |
has an attribute called ``urlconf``, its value will be used in |
|---|
| 39 |
place of the ``ROOT_URLCONF`` setting. |
|---|
| 40 |
2. Django loads that Python module and looks for the variable |
|---|
| 41 |
``urlpatterns``. This should be a Python list, in the format returned by |
|---|
| 42 |
the function ``django.conf.urls.defaults.patterns()``. |
|---|
| 43 |
3. Django runs through each URL pattern, in order, and stops at the first |
|---|
| 44 |
one that matches the requested URL. |
|---|
| 45 |
4. Once one of the regexes matches, Django imports and calls the given |
|---|
| 46 |
view, which is a simple Python function. The view gets passed a |
|---|
| 47 |
`request object`_ as its first argument and any values captured in the |
|---|
| 48 |
regex as remaining arguments. |
|---|
| 49 |
|
|---|
| 50 |
.. _settings file: ../settings/ |
|---|
| 51 |
.. _request object: ../request_response/#httprequest-objects |
|---|
| 52 |
|
|---|
| 53 |
Example |
|---|
| 54 |
======= |
|---|
| 55 |
|
|---|
| 56 |
Here's a sample URLconf:: |
|---|
| 57 |
|
|---|
| 58 |
from django.conf.urls.defaults import * |
|---|
| 59 |
|
|---|
| 60 |
urlpatterns = patterns('', |
|---|
| 61 |
(r'^articles/2003/$', 'news.views.special_case_2003'), |
|---|
| 62 |
(r'^articles/(\d{4})/$', 'news.views.year_archive'), |
|---|
| 63 |
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'), |
|---|
| 64 |
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'), |
|---|
| 65 |
) |
|---|
| 66 |
|
|---|
| 67 |
Notes: |
|---|
| 68 |
|
|---|
| 69 |
* ``from django.conf.urls.defaults import *`` makes the ``patterns()`` |
|---|
| 70 |
function available. |
|---|
| 71 |
|
|---|
| 72 |
* To capture a value from the URL, just put parenthesis around it. |
|---|
| 73 |
|
|---|
| 74 |
* There's no need to add a leading slash, because every URL has that. For |
|---|
| 75 |
example, it's ``^articles``, not ``^/articles``. |
|---|
| 76 |
|
|---|
| 77 |
* The ``'r'`` in front of each regular expression string is optional but |
|---|
| 78 |
recommended. It tells Python that a string is "raw" -- that nothing in |
|---|
| 79 |
the string should be escaped. See `Dive Into Python's explanation`_. |
|---|
| 80 |
|
|---|
| 81 |
Example requests: |
|---|
| 82 |
|
|---|
| 83 |
* A request to ``/articles/2005/03/`` would match the third entry in the |
|---|
| 84 |
list. Django would call the function |
|---|
| 85 |
``news.views.month_archive(request, '2005', '03')``. |
|---|
| 86 |
|
|---|
| 87 |
* ``/articles/2005/3/`` would not match any URL patterns, because the |
|---|
| 88 |
third entry in the list requires two digits for the month. |
|---|
| 89 |
|
|---|
| 90 |
* ``/articles/2003/`` would match the first pattern in the list, not the |
|---|
| 91 |
second one, because the patterns are tested in order, and the first one |
|---|
| 92 |
is the first test to pass. Feel free to exploit the ordering to insert |
|---|
| 93 |
special cases like this. |
|---|
| 94 |
|
|---|
| 95 |
* ``/articles/2003`` would not match any of these patterns, because each |
|---|
| 96 |
pattern requires that the URL end with a slash. |
|---|
| 97 |
|
|---|
| 98 |
* ``/articles/2003/03/3/`` would match the final pattern. Django would call |
|---|
| 99 |
the function ``news.views.article_detail(request, '2003', '03', '3')``. |
|---|
| 100 |
|
|---|
| 101 |
.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 |
|---|
| 102 |
|
|---|
| 103 |
Named groups |
|---|
| 104 |
============ |
|---|
| 105 |
|
|---|
| 106 |
The above example used simple, *non-named* regular-expression groups (via |
|---|
| 107 |
parenthesis) to capture bits of the URL and pass them as *positional* arguments |
|---|
| 108 |
to a view. In more advanced usage, it's possible to use *named* |
|---|
| 109 |
regular-expression groups to capture URL bits and pass them as *keyword* |
|---|
| 110 |
arguments to a view. |
|---|
| 111 |
|
|---|
| 112 |
In Python regular expressions, the syntax for named regular-expression groups |
|---|
| 113 |
is ``(?P<name>pattern)``, where ``name`` is the name of the group and |
|---|
| 114 |
``pattern`` is some pattern to match. |
|---|
| 115 |
|
|---|
| 116 |
Here's the above example URLconf, rewritten to use named groups:: |
|---|
| 117 |
|
|---|
| 118 |
urlpatterns = patterns('', |
|---|
| 119 |
(r'^articles/2003/$', 'news.views.special_case_2003'), |
|---|
| 120 |
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), |
|---|
| 121 |
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), |
|---|
| 122 |
(r'^articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'news.views.article_detail'), |
|---|
| 123 |
) |
|---|
| 124 |
|
|---|
| 125 |
This accomplishes exactly the same thing as the previous example, with one |
|---|
| 126 |
subtle difference: The captured values are passed to view functions as keyword |
|---|
| 127 |
arguments rather than positional arguments. For example: |
|---|
| 128 |
|
|---|
| 129 |
* A request to ``/articles/2005/03/`` would call the function |
|---|
| 130 |
``news.views.month_archive(request, year='2005', month='03')``, instead |
|---|
| 131 |
of ``news.views.month_archive(request, '2005', '03')``. |
|---|
| 132 |
|
|---|
| 133 |
* A request to ``/articles/2003/03/3/`` would call the function |
|---|
| 134 |
``news.views.article_detail(request, year='2003', month='03', day='3')``. |
|---|
| 135 |
|
|---|
| 136 |
In practice, this means your URLconfs are slightly more explicit and less prone |
|---|
| 137 |
to argument-order bugs -- and you can reorder the arguments in your views' |
|---|
| 138 |
function definitions. Of course, these benefits come at the cost of brevity; |
|---|
| 139 |
some developers find the named-group syntax ugly and too verbose. |
|---|
| 140 |
|
|---|
| 141 |
The matching/grouping algorithm |
|---|
| 142 |
------------------------------- |
|---|
| 143 |
|
|---|
| 144 |
Here's the algorithm the URLconf parser follows, with respect to named groups |
|---|
| 145 |
vs. non-named groups in a regular expression: |
|---|
| 146 |
|
|---|
| 147 |
If there are any named arguments, it will use those, ignoring non-named arguments. |
|---|
| 148 |
Otherwise, it will pass all non-named arguments as positional arguments. |
|---|
| 149 |
|
|---|
| 150 |
In both cases, it will pass any extra keyword arguments as keyword arguments. |
|---|
| 151 |
See "Passing extra options to view functions" below. |
|---|
| 152 |
|
|---|
| 153 |
What the URLconf searches against |
|---|
| 154 |
================================= |
|---|
| 155 |
|
|---|
| 156 |
The URLconf searches against the requested URL, as a normal Python string. This |
|---|
| 157 |
does not include GET or POST parameters, or the domain name. |
|---|
| 158 |
|
|---|
| 159 |
For example, in a request to ``http://www.example.com/myapp/``, the URLconf |
|---|
| 160 |
will look for ``/myapp/``. |
|---|
| 161 |
|
|---|
| 162 |
In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look |
|---|
| 163 |
for ``/myapp/``. |
|---|
| 164 |
|
|---|
| 165 |
The URLconf doesn't look at the request method. In other words, all request |
|---|
| 166 |
methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same |
|---|
| 167 |
function for the same URL. |
|---|
| 168 |
|
|---|
| 169 |
Syntax of the urlpatterns variable |
|---|
| 170 |
================================== |
|---|
| 171 |
|
|---|
| 172 |
``urlpatterns`` should be a Python list, in the format returned by the function |
|---|
| 173 |
``django.conf.urls.defaults.patterns()``. Always use ``patterns()`` to create |
|---|
| 174 |
the ``urlpatterns`` variable. |
|---|
| 175 |
|
|---|
| 176 |
Convention is to use ``from django.conf.urls.defaults import *`` at the top of |
|---|
| 177 |
your URLconf. This gives your module access to these objects: |
|---|
| 178 |
|
|---|
| 179 |
patterns |
|---|
| 180 |
-------- |
|---|
| 181 |
|
|---|
| 182 |
A function that takes a prefix, and an arbitrary number of URL patterns, and |
|---|
| 183 |
returns a list of URL patterns in the format Django needs. |
|---|
| 184 |
|
|---|
| 185 |
The first argument to ``patterns()`` is a string ``prefix``. See |
|---|
| 186 |
"The view prefix" below. |
|---|
| 187 |
|
|---|
| 188 |
The remaining arguments should be tuples in this format:: |
|---|
| 189 |
|
|---|
| 190 |
(regular expression, Python callback function [, optional dictionary [, optional name]]) |
|---|
| 191 |
|
|---|
| 192 |
...where ``optional dictionary`` and ``optional name`` are optional. (See |
|---|
| 193 |
`Passing extra options to view functions`_ below.) |
|---|
| 194 |
|
|---|
| 195 |
.. note:: |
|---|
| 196 |
Because `patterns()` is a function call, it accepts a maximum of 255 |
|---|
| 197 |
arguments (URL patterns, in this case). This is a limit for all Python |
|---|
| 198 |
function calls. This is rarely a problem in practice, because you'll |
|---|
| 199 |
typically structure your URL patterns modularly by using `include()` |
|---|
| 200 |
sections. However, on the off-chance you do hit the 255-argument limit, |
|---|
| 201 |
realize that `patterns()` returns a Python list, so you can split up the |
|---|
| 202 |
construction of the list. |
|---|
| 203 |
|
|---|
| 204 |
:: |
|---|
| 205 |
|
|---|
| 206 |
urlpatterns = patterns('', |
|---|
| 207 |
... |
|---|
| 208 |
) |
|---|
| 209 |
urlpatterns += patterns('', |
|---|
| 210 |
... |
|---|
| 211 |
) |
|---|
| 212 |
|
|---|
| 213 |
Python lists have unlimited size, so there's no limit to how many URL |
|---|
| 214 |
patterns you can construct. The only limit is that you can only create 254 |
|---|
| 215 |
at a time (the 255th argument is the initial prefix argument). |
|---|
| 216 |
|
|---|
| 217 |
url |
|---|
| 218 |
--- |
|---|
| 219 |
|
|---|
| 220 |
**New in Django development version** |
|---|
| 221 |
|
|---|
| 222 |
You can use the ``url()`` function, instead of a tuple, as an argument to |
|---|
| 223 |
``patterns()``. This is convenient if you want to specify a name without the |
|---|
| 224 |
optional extra arguments dictionary. For example:: |
|---|
| 225 |
|
|---|
| 226 |
urlpatterns = patterns('', |
|---|
| 227 |
url(r'/index/$', index_view, name="main-view"), |
|---|
| 228 |
... |
|---|
| 229 |
) |
|---|
| 230 |
|
|---|
| 231 |
This function takes five arguments, most of which are optional:: |
|---|
| 232 |
|
|---|
| 233 |
url(regex, view, kwargs=None, name=None, prefix='') |
|---|
| 234 |
|
|---|
| 235 |
See `Naming URL patterns`_ for why the ``name`` parameter is useful. |
|---|
| 236 |
|
|---|
| 237 |
The ``prefix`` parameter has the same meaning as the first argument to |
|---|
| 238 |
``patterns()`` and is only relevant when you're passing a string as the |
|---|
| 239 |
``view`` parameter. |
|---|
| 240 |
|
|---|
| 241 |
handler404 |
|---|
| 242 |
---------- |
|---|
| 243 |
|
|---|
| 244 |
A string representing the full Python import path to the view that should be |
|---|
| 245 |
called if none of the URL patterns match. |
|---|
| 246 |
|
|---|
| 247 |
By default, this is ``'django.views.defaults.page_not_found'``. That default |
|---|
| 248 |
value should suffice. |
|---|
| 249 |
|
|---|
| 250 |
handler500 |
|---|
| 251 |
---------- |
|---|
| 252 |
|
|---|
| 253 |
A string representing the full Python import path to the view that should be |
|---|
| 254 |
called in case of server errors. Server errors happen when you have runtime |
|---|
| 255 |
errors in view code. |
|---|
| 256 |
|
|---|
| 257 |
By default, this is ``'django.views.defaults.server_error'``. That default |
|---|
| 258 |
value should suffice. |
|---|
| 259 |
|
|---|
| 260 |
include |
|---|
| 261 |
------- |
|---|
| 262 |
|
|---|
| 263 |
A function that takes a full Python import path to another URLconf that should |
|---|
| 264 |
be "included" in this place. See `Including other URLconfs`_ below. |
|---|
| 265 |
|
|---|
| 266 |
Notes on capturing text in URLs |
|---|
| 267 |
=============================== |
|---|
| 268 |
|
|---|
| 269 |
Each captured argument is sent to the view as a plain Python string, regardless |
|---|
| 270 |
of what sort of match the regular expression makes. For example, in this |
|---|
| 271 |
URLconf line:: |
|---|
| 272 |
|
|---|
| 273 |
(r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), |
|---|
| 274 |
|
|---|
| 275 |
...the ``year`` argument to ``news.views.year_archive()`` will be a string, not |
|---|
| 276 |
an integer, even though the ``\d{4}`` will only match integer strings. |
|---|
| 277 |
|
|---|
| 278 |
A convenient trick is to specify default parameters for your views' arguments. |
|---|
| 279 |
Here's an example URLconf and view:: |
|---|
| 280 |
|
|---|
| 281 |
# URLconf |
|---|
| 282 |
urlpatterns = patterns('', |
|---|
| 283 |
(r'^blog/$', 'blog.views.page'), |
|---|
| 284 |
(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'), |
|---|
| 285 |
) |
|---|
| 286 |
|
|---|
| 287 |
# View (in blog/views.py) |
|---|
| 288 |
def page(request, num="1"): |
|---|
| 289 |
# Output the appropriate page of blog entries, according to num. |
|---|
| 290 |
|
|---|
| 291 |
In the above example, both URL patterns point to the same view -- |
|---|
| 292 |
``blog.views.page`` -- but the first pattern doesn't capture anything from the |
|---|
| 293 |
URL. If the first pattern matches, the ``page()`` function will use its |
|---|
| 294 |
default argument for ``num``, ``"1"``. If the second pattern matches, |
|---|
| 295 |
``page()`` will use whatever ``num`` value was captured by the regex. |
|---|
| 296 |
|
|---|
| 297 |
Performance |
|---|
| 298 |
=========== |
|---|
| 299 |
|
|---|
| 300 |
Each regular expression in a ``urlpatterns`` is compiled the first time it's |
|---|
| 301 |
accessed. This makes the system blazingly fast. |
|---|
| 302 |
|
|---|
| 303 |
The view prefix |
|---|
| 304 |
=============== |
|---|
| 305 |
|
|---|
| 306 |
You can specify a common prefix in your ``patterns()`` call, to cut down on |
|---|
| 307 |
code duplication. |
|---|
| 308 |
|
|---|
| 309 |
Here's the example URLconf from the `Django overview`_:: |
|---|
| 310 |
|
|---|
| 311 |
from django.conf.urls.defaults import * |
|---|
| 312 |
|
|---|
| 313 |
urlpatterns = patterns('', |
|---|
| 314 |
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'), |
|---|
| 315 |
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'), |
|---|
| 316 |
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'), |
|---|
| 317 |
) |
|---|
| 318 |
|
|---|
| 319 |
In this example, each view has a common prefix -- ``'mysite.news.views'``. |
|---|
| 320 |
Instead of typing that out for each entry in ``urlpatterns``, you can use the |
|---|
| 321 |
first argument to the ``patterns()`` function to specify a prefix to apply to |
|---|
| 322 |
each view function. |
|---|
| 323 |
|
|---|
| 324 |
With this in mind, the above example can be written more concisely as:: |
|---|
| 325 |
|
|---|
| 326 |
from django.conf.urls.defaults import * |
|---|
| 327 |
|
|---|
| 328 |
urlpatterns = patterns('mysite.news.views', |
|---|
| 329 |
(r'^articles/(\d{4})/$', 'year_archive'), |
|---|
| 330 |
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'), |
|---|
| 331 |
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'), |
|---|
| 332 |
) |
|---|
| 333 |
|
|---|
| 334 |
Note that you don't put a trailing dot (``"."``) in the prefix. Django puts |
|---|
| 335 |
that in automatically. |
|---|
| 336 |
|
|---|
| 337 |
.. _Django overview: ../overview/ |
|---|
| 338 |
|
|---|
| 339 |
Multiple view prefixes |
|---|
| 340 |
---------------------- |
|---|
| 341 |
|
|---|
| 342 |
In practice, you'll probably end up mixing and matching views to the point |
|---|
| 343 |
where the views in your ``urlpatterns`` won't have a common prefix. However, |
|---|
| 344 |
you can still take advantage of the view prefix shortcut to remove duplication. |
|---|
| 345 |
Just add multiple ``patterns()`` objects together, like this: |
|---|
| 346 |
|
|---|
| 347 |
Old:: |
|---|
| 348 |
|
|---|
| 349 |
from django.conf.urls.defaults import * |
|---|
| 350 |
|
|---|
| 351 |
urlpatterns = patterns('', |
|---|
| 352 |
(r'^$', 'django.views.generic.date_based.archive_index'), |
|---|
| 353 |
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'), |
|---|
| 354 |
(r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'), |
|---|
| 355 |
) |
|---|
| 356 |
|
|---|
| 357 |
New:: |
|---|
| 358 |
|
|---|
| 359 |
from django.conf.urls.defaults import * |
|---|
| 360 |
|
|---|
| 361 |
urlpatterns = patterns('django.views.generic.date_based', |
|---|
| 362 |
(r'^$', 'archive_index'), |
|---|
| 363 |
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'), |
|---|
| 364 |
) |
|---|
| 365 |
|
|---|
| 366 |
urlpatterns += patterns('weblog.views', |
|---|
| 367 |
(r'^tag/(?P<tag>\w+)/$', 'tag'), |
|---|
| 368 |
) |
|---|
| 369 |
|
|---|
| 370 |
Including other URLconfs |
|---|
| 371 |
======================== |
|---|
| 372 |
|
|---|
| 373 |
At any point, your ``urlpatterns`` can "include" other URLconf modules. This |
|---|
| 374 |
essentially "roots" a set of URLs below other ones. |
|---|
| 375 |
|
|---|
| 376 |
For example, here's the URLconf for the `Django website`_ itself. It includes a |
|---|
| 377 |
number of other URLconfs:: |
|---|
| 378 |
|
|---|
| 379 |
from django.conf.urls.defaults import * |
|---|
| 380 |
|
|---|
| 381 |
urlpatterns = patterns('', |
|---|
| 382 |
(r'^weblog/', include('django_website.apps.blog.urls.blog')), |
|---|
| 383 |
(r'^documentation/', include('django_website.apps.docs.urls.docs')), |
|---|
| 384 |
(r'^comments/', include('django.contrib.comments.urls.comments')), |
|---|
| 385 |
) |
|---|
| 386 |
|
|---|
| 387 |
Note that the regular expressions in this example don't have a ``$`` |
|---|
| 388 |
(end-of-string match character) but do include a trailing slash. Whenever |
|---|
| 389 |
Django encounters ``include()``, it chops off whatever part of the URL matched |
|---|
| 390 |
up to that point and sends the remaining string to the included URLconf for |
|---|
| 391 |
further processing. |
|---|
| 392 |
|
|---|
| 393 |
.. _`Django website`: http://www.djangoproject.com/ |
|---|
| 394 |
|
|---|
| 395 |
Captured parameters |
|---|
| 396 |
------------------- |
|---|
| 397 |
|
|---|
| 398 |
An included URLconf receives any captured parameters from parent URLconfs, so |
|---|
| 399 |
the following example is valid:: |
|---|
| 400 |
|
|---|
| 401 |
# In settings/urls/main.py |
|---|
| 402 |
urlpatterns = patterns('', |
|---|
| 403 |
(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')), |
|---|
| 404 |
) |
|---|
| 405 |
|
|---|
| 406 |
# In foo/urls/blog.py |
|---|
| 407 |
urlpatterns = patterns('foo.views', |
|---|
| 408 |
(r'^$', 'blog.index'), |
|---|
| 409 |
(r'^archive/$', 'blog.archive'), |
|---|
| 410 |
) |
|---|
| 411 |
|
|---|
| 412 |
In the above example, the captured ``"username"`` variable is passed to the |
|---|
| 413 |
included URLconf, as expected. |
|---|
| 414 |
|
|---|
| 415 |
Passing extra options to view functions |
|---|
| 416 |
======================================= |
|---|
| 417 |
|
|---|
| 418 |
URLconfs have a hook that lets you pass extra arguments to your view functions, |
|---|
| 419 |
as a Python dictionary. |
|---|
| 420 |
|
|---|
| 421 |
Any URLconf tuple can have an optional third element, which should be a |
|---|
| 422 |
dictionary of extra keyword arguments to pass to the view function. |
|---|
| 423 |
|
|---|
| 424 |
For example:: |
|---|
| 425 |
|
|---|
| 426 |
urlpatterns = patterns('blog.views', |
|---|
| 427 |
(r'^blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}), |
|---|
| 428 |
) |
|---|
| 429 |
|
|---|
| 430 |
In this example, for a request to ``/blog/2005/``, Django will call the |
|---|
| 431 |
``blog.views.year_archive()`` view, passing it these keyword arguments:: |
|---|
| 432 |
|
|---|
| 433 |
year='2005', foo='bar' |
|---|
| 434 |
|
|---|
| 435 |
This technique is used in `generic views`_ and in the `syndication framework`_ |
|---|
| 436 |
to pass metadata and options to views. |
|---|
| 437 |
|
|---|
| 438 |
.. _generic views: ../generic_views/ |
|---|
| 439 |
.. _syndication framework: ../syndication_feeds/ |
|---|
| 440 |
|
|---|
| 441 |
.. admonition:: Dealing with conflicts |
|---|
| 442 |
|
|---|
| 443 |
It's possible to have a URL pattern which captures named keyword arguments, |
|---|
| 444 |
and also passes arguments with the same names in its dictionary of extra |
|---|
| 445 |
arguments. When this happens, the arguments in the dictionary will be used |
|---|
| 446 |
instead of the arguments captured in the URL. |
|---|
| 447 |
|
|---|
| 448 |
Passing extra options to ``include()`` |
|---|
| 449 |
-------------------------------------- |
|---|
| 450 |
|
|---|
| 451 |
Similarly, you can pass extra options to ``include()``. When you pass extra |
|---|
| 452 |
options to ``include()``, *each* line in the included URLconf will be passed |
|---|
| 453 |
the extra options. |
|---|
| 454 |
|
|---|
| 455 |
For example, these two URLconf sets are functionally identical: |
|---|
| 456 |
|
|---|
| 457 |
Set one:: |
|---|
| 458 |
|
|---|
| 459 |
# main.py |
|---|
| 460 |
urlpatterns = patterns('', |
|---|
| 461 |
(r'^blog/', include('inner'), {'blogid': 3}), |
|---|
| 462 |
) |
|---|
| 463 |
|
|---|
| 464 |
# inner.py |
|---|
| 465 |
urlpatterns = patterns('', |
|---|
| 466 |
(r'^archive/$', 'mysite.views.archive'), |
|---|
| 467 |
(r'^about/$', 'mysite.views.about'), |
|---|
| 468 |
) |
|---|
| 469 |
|
|---|
| 470 |
Set two:: |
|---|
| 471 |
|
|---|
| 472 |
# main.py |
|---|
| 473 |
urlpatterns = patterns('', |
|---|
| 474 |
(r'^blog/', include('inner')), |
|---|
| 475 |
) |
|---|
| 476 |
|
|---|
| 477 |
# inner.py |
|---|
| 478 |
urlpatterns = patterns('', |
|---|
| 479 |
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}), |
|---|
| 480 |
(r'^about/$', 'mysite.views.about', {'blogid': 3}), |
|---|
| 481 |
) |
|---|
| 482 |
|
|---|
| 483 |
Note that extra options will *always* be passed to *every* line in the included |
|---|
| 484 |
URLconf, regardless of whether the line's view actually accepts those options |
|---|
| 485 |
as valid. For this reason, this technique is only useful if you're certain that |
|---|
| 486 |
every view in the the included URLconf accepts the extra options you're passing. |
|---|
| 487 |
|
|---|
| 488 |
Passing callable objects instead of strings |
|---|
| 489 |
=========================================== |
|---|
| 490 |
|
|---|
| 491 |
Some developers find it more natural to pass the actual Python function object |
|---|
| 492 |
rather than a string containing the path to its module. This alternative is |
|---|
| 493 |
supported -- you can pass any callable object as the view. |
|---|
| 494 |
|
|---|
| 495 |
For example, given this URLconf in "string" notation:: |
|---|
| 496 |
|
|---|
| 497 |
urlpatterns = patterns('', |
|---|
| 498 |
(r'^archive/$', 'mysite.views.archive'), |
|---|
| 499 |
(r'^about/$', 'mysite.views.about'), |
|---|
| 500 |
(r'^contact/$', 'mysite.views.contact'), |
|---|
| 501 |
) |
|---|
| 502 |
|
|---|
| 503 |
You can accomplish the same thing by passing objects rather than strings. Just |
|---|
| 504 |
be sure to import the objects:: |
|---|
| 505 |
|
|---|
| 506 |
from mysite.views import archive, about, contact |
|---|
| 507 |
|
|---|
| 508 |
urlpatterns = patterns('', |
|---|
| 509 |
(r'^archive/$', archive), |
|---|
| 510 |
(r'^about/$', about), |
|---|
| 511 |
(r'^contact/$', contact), |
|---|
| 512 |
) |
|---|
| 513 |
|
|---|
| 514 |
The following example is functionally identical. It's just a bit more compact |
|---|
| 515 |
because it imports the module that contains the views, rather than importing |
|---|
| 516 |
each view individually:: |
|---|
| 517 |
|
|---|
| 518 |
from mysite import views |
|---|
| 519 |
|
|---|
| 520 |
urlpatterns = patterns('', |
|---|
| 521 |
(r'^archive/$', views.archive), |
|---|
| 522 |
(r'^about/$', views.about), |
|---|
| 523 |
(r'^contact/$', views.contact), |
|---|
| 524 |
) |
|---|
| 525 |
|
|---|
| 526 |
The style you use is up to you. |
|---|
| 527 |
|
|---|
| 528 |
Note that if you use this technique -- passing objects rather than strings -- |
|---|
| 529 |
the view prefix (as explained in "The view prefix" above) will have no effect. |
|---|
| 530 |
|
|---|
| 531 |
Naming URL patterns |
|---|
| 532 |
=================== |
|---|
| 533 |
|
|---|
| 534 |
**New in Django development version** |
|---|
| 535 |
|
|---|
| 536 |
It's fairly common to use the same view function in multiple URL patterns in |
|---|
| 537 |
your URLconf. For example, these two URL patterns both point to the ``archive`` |
|---|
| 538 |
view:: |
|---|
| 539 |
|
|---|
| 540 |
urlpatterns = patterns('', |
|---|
| 541 |
(r'/archive/(\d{4})/$', archive), |
|---|
| 542 |
(r'/archive-summary/(\d{4})/$', archive, {'summary': True}), |
|---|
| 543 |
) |
|---|
| 544 |
|
|---|
| 545 |
This is completely valid, but it leads to problems when you try to do reverse |
|---|
| 546 |
URL matching (through the ``permalink()`` decorator or the ``{% url %}`` |
|---|
| 547 |
`template tag`_). Continuing this example, if you wanted to retrieve the URL for |
|---|
| 548 |
the ``archive`` view, Django's reverse URL matcher would get confused, because |
|---|
| 549 |
*two* URLpatterns point at that view. |
|---|
| 550 |
|
|---|
| 551 |
To solve this problem, Django supports **named URL patterns**. That is, you can |
|---|
| 552 |
give a name to a URL pattern in order to distinguish it from other patterns |
|---|
| 553 |
using the same view and parameters. Then, you can use this name in reverse URL |
|---|
| 554 |
matching. |
|---|
| 555 |
|
|---|
| 556 |
Here's the above example, rewritten to used named URL patterns:: |
|---|
| 557 |
|
|---|
| 558 |
urlpatterns = patterns('', |
|---|
| 559 |
url(r'/archive/(\d{4})/$', archive, name="full-archive"), |
|---|
| 560 |
url(r'/archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"), |
|---|
| 561 |
) |
|---|
| 562 |
|
|---|
| 563 |
With these names in place (``full-archive`` and ``arch-summary``), you can |
|---|
| 564 |
target each pattern individually by using its name:: |
|---|
| 565 |
|
|---|
| 566 |
{% url arch-summary 1945 %} |
|---|
| 567 |
{% url full-archive 2007 %} |
|---|
| 568 |
|
|---|
| 569 |
Even though both URL patterns refer to the ``archive`` view here, using the |
|---|
| 570 |
``name`` parameter to ``url()`` allows you to tell them apart in templates. |
|---|
| 571 |
|
|---|
| 572 |
The string used for the URL name can contain any characters you like. You are |
|---|
| 573 |
not restricted to valid Python names. |
|---|
| 574 |
|
|---|
| 575 |
.. note:: |
|---|
| 576 |
|
|---|
| 577 |
When you name your URL patterns, make sure you use names that are unlikely |
|---|
| 578 |
to clash with any other application's choice of names. If you call your URL |
|---|
| 579 |
pattern ``comment``, and another application does the same thing, there's |
|---|
| 580 |
no guarantee which URL will be inserted into your template when you use |
|---|
| 581 |
this name. |
|---|
| 582 |
|
|---|
| 583 |
Putting a prefix on your URL names, perhaps derived from the application |
|---|
| 584 |
name, will decrease the chances of collision. We recommend something like |
|---|
| 585 |
``myapp-comment`` instead of ``comment``. |
|---|
| 586 |
|
|---|
| 587 |
.. _template tag: ../templates/#url |
|---|
| 588 |
|
|---|
| 589 |
Utility methods |
|---|
| 590 |
=============== |
|---|
| 591 |
|
|---|
| 592 |
reverse() |
|---|
| 593 |
--------- |
|---|
| 594 |
|
|---|
| 595 |
If you need to use something similar to the ``{% url %}`` `template tag`_ in |
|---|
| 596 |
your code, Django provides the ``django.core.urlresolvers.reverse()``. The |
|---|
| 597 |
``reverse()`` function has the following signature:: |
|---|
| 598 |
|
|---|
| 599 |
reverse(viewname, urlconf=None, args=None, kwargs=None) |
|---|
| 600 |
|
|---|
| 601 |
``viewname`` is either the function name (either a function reference, or the |
|---|
| 602 |
string version of the name, if you used that form in ``urlpatterns``) or the |
|---|
| 603 |
`URL pattern name`_. Normally, you won't need to worry about the |
|---|
| 604 |
``urlconf`` parameter and will only pass in the positional and keyword |
|---|
| 605 |
arguments to use in the URL matching. For example:: |
|---|
| 606 |
|
|---|
| 607 |
from django.core.urlresolvers import reverse |
|---|
| 608 |
|
|---|
| 609 |
def myview(request): |
|---|
| 610 |
return HttpResponseRedirect(reverse('arch-summary', args=[1945])) |
|---|
| 611 |
|
|---|
| 612 |
.. _URL pattern name: `Naming URL patterns`_ |
|---|
| 613 |
|
|---|
| 614 |
permalink() |
|---|
| 615 |
----------- |
|---|
| 616 |
|
|---|
| 617 |
The ``permalink()`` decorator is useful for writing short methods that return |
|---|
| 618 |
a full URL path. For example, a model's ``get_absolute_url()`` method. Refer |
|---|
| 619 |
to the `model API documentation`_ for more information about ``permalink()``. |
|---|
| 620 |
|
|---|
| 621 |
.. _model API documentation: ../model-api/#the-permalink-decorator |
|---|