| 5 | | We're fanatics about good URLs. No ".php" or ".cgi", and certainly not any of |
|---|
| 6 | | that "0,2097,1-1-1928,00" nonsense. Django's URL dispatcher lets you design |
|---|
| 7 | | your URLs to be as pretty as the rest of your application. |
|---|
| 8 | | |
|---|
| 9 | | See `the Django overview`_ for a quick introduction to URL configurations; this |
|---|
| 10 | | document will continue from there. |
|---|
| 11 | | |
|---|
| 12 | | .. _`the Django overview`: http://www.djangoproject.com/documentation/overview/#design-your-urls |
|---|
| | 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 | .. _http://www.w3.org/Provider/Style/URI: Cool URIs don't change |
|---|
| | 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. The system looks at the ``ROOT_URLCONF`` setting in your |
|---|
| | 36 | `settings file`_. This should be a string representing the full Python |
|---|
| | 37 | import path to your URLconf. For example: ``"mydjangoapps.urls"``. |
|---|
| | 38 | 2. The system loads that Python module and looks for the variable |
|---|
| | 39 | ``urlpatterns``. This should be a Python list, in the format returned |
|---|
| | 40 | by the function ``django.conf.urls.defaults.patterns()``. |
|---|
| | 41 | 3. The system runs through each URL pattern, in order, and stops at the |
|---|
| | 42 | first 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`_ and any values captured in the regex as keyword |
|---|
| | 46 | arguments. |
|---|
| | 47 | |
|---|
| | 48 | .. _settings file: http://www.djangoproject.com/documentation/settings/ |
|---|
| | 49 | .. _request object: http://www.djangoproject.com/documentation/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/(?P<year>\d{4})/$', 'news.views.year_archive'), |
|---|
| | 61 | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'news.views.month_archive'), |
|---|
| | 62 | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\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, use the syntax ``(?P<name>pattern)``, |
|---|
| | 71 | where ``name`` is the name for that value and ``pattern`` is some pattern |
|---|
| | 72 | to match. |
|---|
| | 73 | |
|---|
| | 74 | * The ``"r"`` in front of each regular expression string is optional but |
|---|
| | 75 | recommended. It tells Python that a string is "raw" -- that nothing in |
|---|
| | 76 | the string should be escaped. See `Dive Into Python's explanation`_. |
|---|
| | 77 | |
|---|
| | 78 | Examples: |
|---|
| | 79 | |
|---|
| | 80 | * A request to ``/articles/2005/03/`` would match the third entry in the |
|---|
| | 81 | list. Django would call the function |
|---|
| | 82 | ``news.views.month_archive(request, year='2005', month='03')``. |
|---|
| | 83 | |
|---|
| | 84 | * ``/articles/2005/3/`` would not match any URL patterns, because the |
|---|
| | 85 | third entry in the list requires two digits for the month. |
|---|
| | 86 | |
|---|
| | 87 | * ``/articles/2003/`` would match the first pattern in the list, not the |
|---|
| | 88 | second one, because the patterns are tested in order, and the first one |
|---|
| | 89 | is the first test to pass. Feel free to exploit the ordering to insert |
|---|
| | 90 | special cases like this. |
|---|
| | 91 | |
|---|
| | 92 | * ``/articles/2003`` would not match any of these patterns, because each |
|---|
| | 93 | pattern requires that the URL end with a slash. |
|---|
| | 94 | |
|---|
| | 95 | * ``/articles/2003/03/3/`` would match the final pattern. Django would call |
|---|
| | 96 | the function |
|---|
| | 97 | ``news.views.article_detail(request, year='2003', month='03', day='3')``. |
|---|
| | 98 | |
|---|
| | 99 | .. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3 |
|---|
| | 100 | |
|---|
| | 101 | What the URLconf searches against |
|---|
| | 102 | ================================= |
|---|
| | 103 | |
|---|
| | 104 | The URLconf searches against the requested URL, as a normal Python string. This |
|---|
| | 105 | does not include GET or POST parameters, or the domain name. |
|---|
| | 106 | |
|---|
| | 107 | For example, in a request to ``http://www.example.com/myapp/``, the URLconf |
|---|
| | 108 | will look for ``/myapp/``. |
|---|
| | 109 | |
|---|
| | 110 | In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look |
|---|
| | 111 | for ``/myapp/``. |
|---|
| | 112 | |
|---|
| | 113 | Syntax of the urlpatterns variable |
|---|
| | 114 | ================================== |
|---|
| | 115 | |
|---|
| | 116 | ``urlpatterns`` should be a Python list, in the format returned by the function |
|---|
| | 117 | ``django.conf.urls.defaults.patterns()``. Always use ``patterns()`` to create |
|---|
| | 118 | the ``urlpatterns`` variable. |
|---|
| | 119 | |
|---|
| | 120 | Convention is to use ``from django.conf.urls.defaults import *`` at the top of |
|---|
| | 121 | your URLconf. This gives your module access to these objects: |
|---|
| | 122 | |
|---|
| | 123 | patterns |
|---|
| | 124 | -------- |
|---|
| | 125 | |
|---|
| | 126 | A function that takes a prefix an arbitrary number of URL patterns and returns |
|---|
| | 127 | a list of URL patterns in the format Django needs. |
|---|
| | 128 | |
|---|
| | 129 | The first argument to ``patterns()`` is a string ``prefix``. See |
|---|
| | 130 | "The view prefix" below. |
|---|
| | 131 | |
|---|
| | 132 | The remaining arguments should be tuples in this format:: |
|---|
| | 133 | |
|---|
| | 134 | (regular expression, Python callback function [, optional dictionary]) |
|---|
| | 135 | |
|---|
| | 136 | ...where ``dictionary_of_extra_arguments`` is optional. (See |
|---|
| | 137 | "Passing extra options to view functions" below.) |
|---|
| | 138 | |
|---|
| | 139 | handler404 |
|---|
| | 140 | ---------- |
|---|
| | 141 | |
|---|
| | 142 | A string representing the full Python import path to the view that should be |
|---|
| | 143 | called if none of the URL patterns match. |
|---|
| | 144 | |
|---|
| | 145 | By default, this is ``'django.views.defaults.page_not_found'``. That default |
|---|
| | 146 | value should suffice. |
|---|
| | 147 | |
|---|
| | 148 | handler500 |
|---|
| | 149 | ---------- |
|---|
| | 150 | |
|---|
| | 151 | A string representing the full Python import path to the view that should be |
|---|
| | 152 | called in case of server errors. Server errors happen when you have runtime |
|---|
| | 153 | errors in view code. |
|---|
| | 154 | |
|---|
| | 155 | By default, this is ``'django.views.defaults.server_error'``. That default |
|---|
| | 156 | value should suffice. |
|---|
| | 157 | |
|---|
| | 158 | include |
|---|
| | 159 | ------- |
|---|
| | 160 | |
|---|
| | 161 | A function that takes a full Python import path to another URLconf that should |
|---|
| | 162 | be "included" in this place. See "Including other URLconfs" below. |
|---|
| | 163 | |
|---|
| | 164 | Notes on capturing text in URLs |
|---|
| | 165 | =============================== |
|---|
| | 166 | |
|---|
| | 167 | Each captured argument is sent to the view as a plain Python string, regardless |
|---|
| | 168 | of what sort of match the regular expression makes. For example, in this |
|---|
| | 169 | URLconf:: |
|---|
| | 170 | |
|---|
| | 171 | (r'^/articles/(?P<year>\d{4})/$', 'news.views.year_archive'), |
|---|
| | 172 | |
|---|
| | 173 | ...the ``year`` argument to ``news.views.year_archive()`` will be a string, not |
|---|
| | 174 | an integer, even though the ``\d{4}`` will only match integer strings. |
|---|
| | 175 | |
|---|
| | 176 | A convenient trick is to specify default parameters for your views' arguments. |
|---|
| | 177 | Here's an example URLconf and view:: |
|---|
| | 178 | |
|---|
| | 179 | # URLconf |
|---|
| | 180 | urlpatterns = patterns('', |
|---|
| | 181 | (r'^/blog/$', 'blog.views.page'), |
|---|
| | 182 | (r'^/blog/page(?P<num>\d+)/$', 'blog.views.page'), |
|---|
| | 183 | ) |
|---|
| | 184 | |
|---|
| | 185 | # View (in blog/views.py) |
|---|
| | 186 | def page(request, num="1"): |
|---|
| | 187 | # Output the appropriate page of blog entries, according to num. |
|---|
| | 188 | |
|---|
| | 189 | In the above example, both URL patterns point to the same view -- |
|---|
| | 190 | ``blog.views.page`` -- but the first pattern doesn't capture anything from the |
|---|
| | 191 | URL. If the first pattern matches, the ``page()`` function will use its |
|---|
| | 192 | default argument for ``num``, ``"1"``. If the second pattern matches, |
|---|
| | 193 | ``page()`` will use whatever ``num`` value was captured by the regex. |
|---|
| | 194 | |
|---|
| | 195 | Performance |
|---|
| | 196 | =========== |
|---|
| | 197 | |
|---|
| | 198 | Each regular expression in a ``urlpatterns`` is compiled the first time it's |
|---|
| | 199 | accessed. This makes the system blazingly fast. |
|---|
| 17 | | Here's the example from that overview:: |
|---|
| 18 | | |
|---|
| 19 | | from django.conf.urls.defaults import * |
|---|
| 20 | | |
|---|
| 21 | | urlpatterns = patterns('', |
|---|
| 22 | | (r'^/articles/(?P<year>\d{4})/$', 'myproject.news.views.articles.year_archive'), |
|---|
| 23 | | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'myproject.news.views.articles.month_archive'), |
|---|
| 24 | | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'myproject.news.views.articles.article_detail'), |
|---|
| 25 | | ) |
|---|
| 26 | | |
|---|
| 27 | | The first argument to ``patterns`` is an empty string in the above example, but |
|---|
| 28 | | that argument can be useful. The first argument is prepended to all the view |
|---|
| 29 | | functions in the urlpatterns list, so the above example could be written more |
|---|
| 30 | | concisely as:: |
|---|
| 31 | | |
|---|
| 32 | | urlpatterns = patterns('myproject.news.views.articles', |
|---|
| | 204 | You can specify a common prefix in your ``patterns()`` call, to cut down on |
|---|
| | 205 | code duplication. |
|---|
| | 206 | |
|---|
| | 207 | Here's the example URLconf from the `Django overview`_:: |
|---|
| | 208 | |
|---|
| | 209 | from django.conf.urls.defaults import * |
|---|
| | 210 | |
|---|
| | 211 | urlpatterns = patterns('', |
|---|
| | 212 | (r'^/articles/(?P<year>\d{4})/$', 'myproject.news.views.year_archive'), |
|---|
| | 213 | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'myproject.news.views.month_archive'), |
|---|
| | 214 | (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'myproject.news.views.article_detail'), |
|---|
| | 215 | ) |
|---|
| | 216 | |
|---|
| | 217 | In this example, each view has a common prefix -- ``"myproject.news.views"``. |
|---|
| | 218 | Instead of typing that out for each entry in ``urlpatterns``, you can use the |
|---|
| | 219 | first argument to the ``patterns()`` function to specify a prefix to apply to |
|---|
| | 220 | each view function. |
|---|
| | 221 | |
|---|
| | 222 | With this in mind, the above example can be written more concisely as:: |
|---|
| | 223 | |
|---|
| | 224 | from django.conf.urls.defaults import * |
|---|
| | 225 | |
|---|
| | 226 | urlpatterns = patterns('myproject.news.views', |
|---|