|
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 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. |
|
47 |
|
48 .. _settings file: ../settings/ |
|
49 .. _request object: ../request_response/#httprequest-objects |
|
50 |
|
51 Example |
|
52 ======= |
|
53 |
|
54 Here's a sample URLconf:: |
|
55 |
|
56 from django.conf.urls.defaults import * |
|
57 |
|
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'), |
|
63 ) |
|
64 |
|
65 Notes: |
|
66 |
|
67 * ``from django.conf.urls.defaults import *`` makes the ``patterns()`` |
|
68 function available. |
|
69 |
|
70 * To capture a value from the URL, just put parenthesis around it. |
|
71 |
|
72 * There's no need to add a leading slash, because every URL has that. For |
|
73 example, it's ``^articles``, not ``^/articles``. |
|
74 |
|
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`_. |
|
78 |
|
79 Example requests: |
|
80 |
|
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')``. |
|
84 |
|
85 * ``/articles/2005/3/`` would not match any URL patterns, because the |
|
86 third entry in the list requires two digits for the month. |
|
87 |
|
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. |
|
92 |
|
93 * ``/articles/2003`` would not match any of these patterns, because each |
|
94 pattern requires that the URL end with a slash. |
|
95 |
|
96 * ``/articles/2003/03/3/`` would match the final pattern. Django would call |
|
97 the function ``news.views.article_detail(request, '2003', '03', '3')``. |
|
98 |
|
99 .. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 |
|
100 |
|
101 Named groups |
|
102 ============ |
|
103 |
|
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* |
|
108 arguments to a view. |
|
109 |
|
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. |
|
113 |
|
114 Here's the above example URLconf, rewritten to use named groups:: |
|
115 |
|
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'), |
|
121 ) |
|
122 |
|
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: |
|
126 |
|
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')``. |
|
130 |
|
131 * A request to ``/articles/2003/03/3/`` would call the function |
|
132 ``news.views.article_detail(request, year='2003', month='03', day='3')``. |
|
133 |
|
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. |
|
138 |
|
139 The matching/grouping algorithm |
|
140 ------------------------------- |
|
141 |
|
142 Here's the algorithm the URLconf parser follows, with respect to named groups |
|
143 vs. non-named groups in a regular expression: |
|
144 |
|
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. |
|
147 |
|
148 In both cases, it will pass any extra keyword arguments as keyword arguments. |
|
149 See "Passing extra options to view functions" below. |
|
150 |
|
151 What the URLconf searches against |
|
152 ================================= |
|
153 |
|
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. |
|
156 |
|
157 For example, in a request to ``http://www.example.com/myapp/``, the URLconf |
|
158 will look for ``/myapp/``. |
|
159 |
|
160 In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look |
|
161 for ``/myapp/``. |
|
162 |
|
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. |
|
166 |
|
167 Syntax of the urlpatterns variable |
|
168 ================================== |
|
169 |
|
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. |
|
173 |
|
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: |
|
176 |
|
177 patterns |
|
178 -------- |
|
179 |
|
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. |
|
182 |
|
183 The first argument to ``patterns()`` is a string ``prefix``. See |
|
184 "The view prefix" below. |
|
185 |
|
186 The remaining arguments should be tuples in this format:: |
|
187 |
|
188 (regular expression, Python callback function [, optional dictionary]) |
|
189 |
|
190 ...where ``optional dictionary`` is optional. (See |
|
191 _`Passing extra options to view functions` below.) |
|
192 |
|
193 handler404 |
|
194 ---------- |
|
195 |
|
196 A string representing the full Python import path to the view that should be |
|
197 called if none of the URL patterns match. |
|
198 |
|
199 By default, this is ``'django.views.defaults.page_not_found'``. That default |
|
200 value should suffice. |
|
201 |
|
202 handler500 |
|
203 ---------- |
|
204 |
|
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 |
|
207 errors in view code. |
|
208 |
|
209 By default, this is ``'django.views.defaults.server_error'``. That default |
|
210 value should suffice. |
|
211 |
|
212 include |
|
213 ------- |
|
214 |
|
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. |
|
217 |
|
218 Notes on capturing text in URLs |
|
219 =============================== |
|
220 |
|
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 |
|
223 URLconf line:: |
|
224 |
|
225 (r'^articles/(?P<year>\d{4})/$', 'news.views.year_archive'), |
|
226 |
|
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. |
|
229 |
|
230 A convenient trick is to specify default parameters for your views' arguments. |
|
231 Here's an example URLconf and view:: |
|
232 |
|
233 # URLconf |
|
234 urlpatterns = patterns('', |
|
235 (r'^blog/$', 'blog.views.page'), |
|
236 (r'^blog/page(?P<num>\d+)/$', 'blog.views.page'), |
|
237 ) |
|
238 |
|
239 # View (in blog/views.py) |
|
240 def page(request, num="1"): |
|
241 # Output the appropriate page of blog entries, according to num. |
|
242 |
|
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. |
|
248 |
|
249 Performance |
|
250 =========== |
|
251 |
|
252 Each regular expression in a ``urlpatterns`` is compiled the first time it's |
|
253 accessed. This makes the system blazingly fast. |
|
254 |
|
255 The view prefix |
|
256 =============== |
|
257 |
|
258 You can specify a common prefix in your ``patterns()`` call, to cut down on |
|
259 code duplication. |
|
260 |
|
261 Here's the example URLconf from the `Django overview`_:: |
|
262 |
|
263 from django.conf.urls.defaults import * |
|
264 |
|
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'), |
|
269 ) |
|
270 |
|
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 |
|
274 each view function. |
|
275 |
|
276 With this in mind, the above example can be written more concisely as:: |
|
277 |
|
278 from django.conf.urls.defaults import * |
|
279 |
|
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'), |
|
284 ) |
|
285 |
|
286 Note that you don't put a trailing dot (``"."``) in the prefix. Django puts |
|
287 that in automatically. |
|
288 |
|
289 .. _Django overview: ../overview/ |
|
290 |
|
291 Multiple view prefixes |
|
292 ---------------------- |
|
293 |
|
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: |
|
298 |
|
299 Old:: |
|
300 |
|
301 from django.conf.urls.defaults import * |
|
302 |
|
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'), |
|
307 ) |
|
308 |
|
309 New:: |
|
310 |
|
311 from django.conf.urls.defaults import * |
|
312 |
|
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'), |
|
316 ) |
|
317 |
|
318 urlpatterns += patterns('weblog.views', |
|
319 (r'^tag/(?P<tag>\w+)/$', 'tag'), |
|
320 ) |
|
321 |
|
322 Including other URLconfs |
|
323 ======================== |
|
324 |
|
325 At any point, your ``urlpatterns`` can "include" other URLconf modules. This |
|
326 essentially "roots" a set of URLs below other ones. |
|
327 |
|
328 For example, here's the URLconf for the `Django website`_ itself. It includes a |
|
329 number of other URLconfs:: |
|
330 |
|
331 from django.conf.urls.defaults import * |
|
332 |
|
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')), |
|
337 ) |
|
338 |
|
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 |
|
343 further processing. |
|
344 |
|
345 .. _`Django website`: http://www.djangoproject.com/ |
|
346 |
|
347 Captured parameters |
|
348 ------------------- |
|
349 |
|
350 An included URLconf receives any captured parameters from parent URLconfs, so |
|
351 the following example is valid:: |
|
352 |
|
353 # In settings/urls/main.py |
|
354 urlpatterns = patterns('', |
|
355 (r'^(?P<username>\w+)/blog/', include('foo.urls.blog')), |
|
356 ) |
|
357 |
|
358 # In foo/urls/blog.py |
|
359 urlpatterns = patterns('foo.views', |
|
360 (r'^$', 'blog.index'), |
|
361 (r'^archive/$', 'blog.archive'), |
|
362 ) |
|
363 |
|
364 In the above example, the captured ``"username"`` variable is passed to the |
|
365 included URLconf, as expected. |
|
366 |
|
367 Passing extra options to view functions |
|
368 ======================================= |
|
369 |
|
370 URLconfs have a hook that lets you pass extra arguments to your view functions, |
|
371 as a Python dictionary. |
|
372 |
|
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. |
|
375 |
|
376 For example:: |
|
377 |
|
378 urlpatterns = patterns('blog.views', |
|
379 (r'^/blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}), |
|
380 ) |
|
381 |
|
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:: |
|
384 |
|
385 year='2005', foo='bar' |
|
386 |
|
387 This technique is used in `generic views`_ and in the `syndication framework`_ |
|
388 to pass metadata and options to views. |
|
389 |
|
390 .. _generic views: ../generic_views/ |
|
391 .. _syndication framework: ../syndication/ |
|
392 |
|
393 .. admonition:: Dealing with conflicts |
|
394 |
|
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. |
|
399 |
|
400 Passing extra options to ``include()`` |
|
401 -------------------------------------- |
|
402 |
|
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 |
|
405 the extra options. |
|
406 |
|
407 For example, these two URLconf sets are functionally identical: |
|
408 |
|
409 Set one:: |
|
410 |
|
411 # main.py |
|
412 urlpatterns = patterns('', |
|
413 (r'^blog/', include('inner'), {'blogid': 3}), |
|
414 ) |
|
415 |
|
416 # inner.py |
|
417 urlpatterns = patterns('', |
|
418 (r'^archive/$', 'mysite.views.archive'), |
|
419 (r'^about/$', 'mysite.views.about'), |
|
420 ) |
|
421 |
|
422 Set two:: |
|
423 |
|
424 # main.py |
|
425 urlpatterns = patterns('', |
|
426 (r'^blog/', include('inner')), |
|
427 ) |
|
428 |
|
429 # inner.py |
|
430 urlpatterns = patterns('', |
|
431 (r'^archive/$', 'mysite.views.archive', {'blogid': 3}), |
|
432 (r'^about/$', 'mysite.views.about', {'blogid': 3}), |
|
433 ) |
|
434 |
|
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. |
|
439 |
|
440 Passing callable objects instead of strings |
|
441 =========================================== |
|
442 |
|
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. |
|
446 |
|
447 For example, given this URLconf in "string" notation:: |
|
448 |
|
449 urlpatterns = patterns('', |
|
450 (r'^archive/$', 'mysite.views.archive'), |
|
451 (r'^about/$', 'mysite.views.about'), |
|
452 (r'^contact/$', 'mysite.views.contact'), |
|
453 ) |
|
454 |
|
455 You can accomplish the same thing by passing objects rather than strings. Just |
|
456 be sure to import the objects:: |
|
457 |
|
458 from mysite.views import archive, about, contact |
|
459 |
|
460 urlpatterns = patterns('', |
|
461 (r'^archive/$', archive), |
|
462 (r'^about/$', about), |
|
463 (r'^contact/$', contact), |
|
464 ) |
|
465 |
|
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:: |
|
469 |
|
470 from mysite import views |
|
471 |
|
472 urlpatterns = patterns('', |
|
473 (r'^archive/$', views.archive), |
|
474 (r'^about/$', views.about), |
|
475 (r'^contact/$', views.contact), |
|
476 ) |
|
477 |
|
478 The style you use is up to you. |
|
479 |
|
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. |