Browse files

Beefed up docs/url_dispatch.txt

git-svn-id: bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
adrianholovaty committed Nov 19, 2005
1 parent cdbc94d commit f125fb0afc2e00612701f825c8456acdcb53e55b
Showing with 253 additions and 40 deletions.
  1. +6 −6 docs/overview.txt
  2. +10 −4 docs/tutorial03.txt
  3. +237 −30 docs/url_dispatch.txt
@@ -162,9 +162,9 @@ Reporter/Article example, here's what that might look like::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
- (r'^/articles/(?P<year>\d{4})/$', ''),
- (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', ''),
- (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<article_id>\d+)/$', ''),
+ (r'^/articles/(?P<year>\d{4})/$', ''),
+ (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', ''),
+ (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<article_id>\d+)/$', ''),
The code above maps URLs, as regular expressions, to the location of Python
@@ -181,7 +181,7 @@ dictionaries -- and the values captured in the regex, via keyword
For example, if a user requested the URL "/articles/2005/05/39323/", Django
-would call the function ``,
+would call the function ``,
year='2005', month='05', article_id='39323')``.
Write your views
@@ -280,8 +280,8 @@ This has been only a quick overview of Django's functionality. Some more useful
* A caching framework that integrates with memcached or other backends.
- * An RSS framework that makes creating RSS feeds as easy as writing a
- small Python class.
+ * A syndication framework that makes creating RSS and Atom feeds as easy as
+ writing a small Python class.
* More sexy automatically-generated admin features -- this overview barely
scratched the surface.
@@ -60,15 +60,15 @@ regular expression as keyword arguments, and, optionally, arbitrary keyword
arguments from the dictionary (an optional third item in the tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
+For more details on URLconfs, see the `URLconf documentation`_.
When you ran `` startproject myproject`` at the beginning of
Tutorial 1, it created a default URLconf in ``myproject/``. It also
automatically set your ``ROOT_URLCONF`` setting to point at that file::
ROOT_URLCONF = 'myproject.urls'
-Time for an example. Edit ``myproject/`` so it looks like
+Time for an example. Edit ``myproject/`` so it looks like this::
from django.conf.urls.defaults import *
@@ -88,9 +88,9 @@ associated Python package/module: ``myproject.apps.polls.views.detail``. That
corresponds to the function ``detail()`` in ``myproject/apps/polls/``.
Finally, it calls that ``detail()`` function like so::
- detail(request=<HttpRequest object>, poll_id=23)
+ detail(request=<HttpRequest object>, poll_id='23')
-The ``poll_id=23`` part comes from ``(?P<poll_id>\d+)``. Using
+The ``poll_id='23'`` part comes from ``(?P<poll_id>\d+)``. Using
``(?P<name>pattern)`` "captures" the text matched by ``pattern`` and sends it
as a keyword argument to the view function.
@@ -103,6 +103,11 @@ something like this::
But, don't do that. It's silly.
+Note that these regular expressions do not search GET and POST parameters, or
+the domain name. For example, in a request to ````,
+the URLconf will look for ``/myapp/``. In a request to
+````, the URLconf will look for ``/myapp/``.
If you need help with regular expressions, see `Wikipedia's entry`_ and the
`Python documentation`_. Also, the O'Reilly book "Mastering Regular
Expressions" by Jeffrey Friedl is fantastic.
@@ -113,6 +118,7 @@ time the URLconf module is loaded. They're super fast.
.. _Wikipedia's entry:
.. _Python documentation:
.. _request and response documentation:
+.. _URLconf documentation:
Write your first view
@@ -2,52 +2,244 @@
URL dispatcher
-We're fanatics about good URLs. No ".php" or ".cgi", and certainly not any of
-that "0,2097,1-1-1928,00" nonsense. Django's URL dispatcher lets you design
-your URLs to be as pretty as the rest of your application.
+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
-See `the Django overview`_ for a quick introduction to URL configurations; this
-document will continue from there.
+There's no ``.php`` or ``.cgi`` required, and certainly none of that
+``0,2097,1-1-1928,00`` nonsense.
-.. _`the Django overview`:
+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.
+.. _ Cool URIs don't change
+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
+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. The system looks at the ``ROOT_URLCONF`` setting in your
+ `settings file`_. This should be a string representing the full Python
+ import path to your URLconf. For example: ``"mydjangoapps.urls"``.
+ 2. The system 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. The system 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 a
+ `request object`_ and any values captured in the regex as keyword
+ arguments.
+.. _settings file:
+.. _request object:
+Here's a sample URLconf::
+ from django.conf.urls.defaults import *
+ 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'),
+ )
+ * ``from django.conf.urls.defaults import *`` makes the ``patterns``
+ function available.
+ * To capture a value from the URL, use the syntax ``(?P<name>pattern)``,
+ where ``name`` is the name for that value and ``pattern`` is some pattern
+ to match.
+ * 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`_.
+ * A request to ``/articles/2005/03/`` would match the third entry in the
+ list. Django would call the function
+ ``news.views.month_archive(request, year='2005', month='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, year='2003', month='03', day='3')``.
+.. _Dive Into Python's explanation:
+What the URLconf searches against
+The URLconf searches against the requested URL, as a normal Python string. This
+does not include GET or POST parameters, or the domain name.
+For example, in a request to ````, the URLconf
+will look for ``/myapp/``.
+In a request to ````, the URLconf will look
+for ``/myapp/``.
+Syntax of the urlpatterns variable
+``urlpatterns`` should be a Python list, in the format returned by the function
+``django.conf.urls.defaults.patterns()``. Always use ``patterns()`` to create
+the ``urlpatterns`` variable.
+Convention is to use ``from django.conf.urls.defaults import *`` at the top of
+your URLconf. This gives your module access to these objects:
+A function that takes a prefix an arbitrary number of URL patterns and returns
+a list of URL patterns in the format Django needs.
+The first argument to ``patterns()`` is a string ``prefix``. See
+"The view prefix" below.
+The remaining arguments should be tuples in this format::
+ (regular expression, Python callback function [, optional dictionary])
+...where ``dictionary_of_extra_arguments`` is optional. (See
+"Passing extra options to view functions" below.)
+A string representing the full Python import path to the view that should be
+called if none of the URL patterns match.
+By default, this is ``'django.views.defaults.page_not_found'``. That default
+value should suffice.
+A string representing the full Python import path to the view that should be
+called in case of server errors. Server errors happen when you have runtime
+errors in view code.
+By default, this is ``'django.views.defaults.server_error'``. That default
+value should suffice.
+A function that takes a full Python import path to another URLconf that should
+be "included" in this place. See "Including other URLconfs" below.
+Notes on capturing text in URLs
+Each captured argument is sent to the view as a plain Python string, regardless
+of what sort of match the regular expression makes. For example, in this
+ (r'^/articles/(?P<year>\d{4})/$', 'news.views.year_archive'),
+...the ``year`` argument to ``news.views.year_archive()`` will be a string, not
+an integer, even though the ``\d{4}`` will only match integer strings.
+A convenient trick is to specify default parameters for your views' arguments.
+Here's an example URLconf and view::
+ # URLconf
+ urlpatterns = patterns('',
+ (r'^/blog/$', ''),
+ (r'^/blog/page(?P<num>\d+)/$', ''),
+ )
+ # View (in blog/
+ def page(request, num="1"):
+ # Output the appropriate page of blog entries, according to num.
+In the above example, both URL patterns point to the same view --
+```` -- but the first pattern doesn't capture anything from the
+URL. If the first pattern matches, the ``page()`` function will use its
+default argument for ``num``, ``"1"``. If the second pattern matches,
+``page()`` will use whatever ``num`` value was captured by the regex.
+Each regular expression in a ``urlpatterns`` is compiled the first time it's
+accessed. This makes the system blazingly fast.
The view prefix
-Here's the example from that overview::
+You can specify a common prefix in your ``patterns()`` call, to cut down on
+code duplication.
+Here's the example URLconf from the `Django overview`_::
from django.conf.urls.defaults import *
urlpatterns = patterns('',
- (r'^/articles/(?P<year>\d{4})/$', ''),
- (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', ''),
- (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', ''),
+ (r'^/articles/(?P<year>\d{4})/$', ''),
+ (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', ''),
+ (r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', ''),
-The first argument to ``patterns`` is an empty string in the above example, but
-that argument can be useful. The first argument is prepended to all the view
-functions in the urlpatterns list, so the above example could be written more
-concisely as::
+In this example, each view has a common prefix -- ``""``.
+Instead of typing that out for each entry in ``urlpatterns``, you can use the
+first argument to the ``patterns()`` function to specify a prefix to apply to
+each view function.
+With this in mind, the above example can be written more concisely as::
+ from django.conf.urls.defaults import *
- urlpatterns = patterns('',
+ urlpatterns = patterns('',
(r'^/articles/(?P<year>\d{4})/$', 'year_archive'),
(r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/$', 'month_archive'),
(r'^/articles/(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d+)/$', 'article_detail'),
-.. admonition:: Note
- More precisely, the actual view function used is ``prefix + "." +
- function_name``. The trailing "dot" does not need to be put in the prefix.
+Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
+that in automatically.
Including other URLconfs
-You can also "include" other URLconf modules at any point along the path. This
-essentially "roots" a set of URLs below other ones. This is most often used
-for a site's "base" URLconf; the ``ROOT_URLCONF`` setting points to a urlconf
-module that will be used for the entire site. Here's the URLconf for the
-`Django website`_ itself. It includes a number of other URLconfs::
+At any point, your ``urlpatterns`` can "include" other URLconf modules. This
+essentially "roots" a set of URLs below other ones.
+For example, here's the URLconf for the `Django website`_ itself. It includes a
+number of other URLconfs::
from django.conf.urls.defaults import *
@@ -70,6 +262,7 @@ URLconfs, so the following example is valid::
urlpatterns = patterns('foo.views'
(r'^$', 'blog.index'),
(r'^archive/$', 'blog.archive'),
+ )
In the above example, the captured ``"username"`` variable is passed to the
included URLconf, as expected.
@@ -79,11 +272,25 @@ included URLconf, as expected.
Passing extra options to view functions
-There are two ways of passing arguments into your view functions: named captures
-from the regex (which you've already seen) and the optional third element
-in URLconf tuples. This third element can be a dictionary of extra keyword
-arguments that will be passed to the view function::
+URLconfs have a hook that lets you pass extra arguments to your view functions,
+as a Python dictionary.
+Any URLconf tuple can have an optional third element, which should be a
+dictionary of extra keyword arguments to pass to the view function.
+For example::
- urlpatterns = patterns('',
- (r'^/articles/(?P<year>\d{4})/$', 'year_archive', {key: value, key2: value2}),
+ urlpatterns = patterns('blog.views',
+ (r'^/blog/(?P<year>\d{4})/$', 'year_archive', {'foo': 'bar'}),
+In this example, for a request to ``/blog/2005/``, Django will call the
+``blog.views.year_archive()`` view, passing it these keyword arguments::
+ year='2005', foo='bar'
+This technique is used in `generic views`_ and in the `syndication framework`_
+to pass metadata and options to views.
+.. _generic views:
+.. _syndication framework:

0 comments on commit f125fb0

Please sign in to comment.