931 lines
34 KiB
Plaintext
931 lines
34 KiB
Plaintext
.. _topics-http-urls:
|
|
|
|
==============
|
|
URL dispatcher
|
|
==============
|
|
|
|
.. module:: django.core.urlresolvers
|
|
|
|
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
|
|
limitations.
|
|
|
|
There's no ``.php`` or ``.cgi`` required, and certainly none of that
|
|
``0,2097,1-1-1928,00`` nonsense.
|
|
|
|
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: http://www.w3.org/Provider/Style/URI
|
|
|
|
Overview
|
|
========
|
|
|
|
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
|
|
dynamically.
|
|
|
|
.. _how-django-processes-a-request:
|
|
|
|
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. Django determines the root URLconf module to use. Ordinarily,
|
|
this is the value of the ``ROOT_URLCONF`` setting, but if the incoming
|
|
``HttpRequest`` object has an attribute called ``urlconf`` (set by
|
|
middleware :ref:`request processing <request-middleware>`), its value
|
|
will be used in place of the ``ROOT_URLCONF`` setting.
|
|
|
|
2. Django 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. Django 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 an
|
|
:class:`~django.http.HttpRequest` as its first argument and any values
|
|
captured in the regex as remaining arguments.
|
|
|
|
Example
|
|
=======
|
|
|
|
Here's a sample URLconf::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^articles/2003/$', 'news.views.special_case_2003'),
|
|
(r'^articles/(\d{4})/$', 'news.views.year_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
|
|
)
|
|
|
|
Notes:
|
|
|
|
* ``from django.conf.urls.defaults import *`` makes the ``patterns()``
|
|
function available.
|
|
|
|
* To capture a value from the URL, just put parenthesis around it.
|
|
|
|
* There's no need to add a leading slash, because every URL has that. For
|
|
example, it's ``^articles``, not ``^/articles``.
|
|
|
|
* 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`_.
|
|
|
|
Example requests:
|
|
|
|
* A request to ``/articles/2005/03/`` would match the third entry in the
|
|
list. Django would call the function
|
|
``news.views.month_archive(request, '2005', '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, '2003', '03', '3')``.
|
|
|
|
.. _Dive Into Python's explanation: http://diveintopython.org/regular_expressions/street_addresses.html#re.matching.2.3
|
|
|
|
Named groups
|
|
============
|
|
|
|
The above example used simple, *non-named* regular-expression groups (via
|
|
parenthesis) to capture bits of the URL and pass them as *positional* arguments
|
|
to a view. In more advanced usage, it's possible to use *named*
|
|
regular-expression groups to capture URL bits and pass them as *keyword*
|
|
arguments to a view.
|
|
|
|
In Python regular expressions, the syntax for named regular-expression groups
|
|
is ``(?P<name>pattern)``, where ``name`` is the name of the group and
|
|
``pattern`` is some pattern to match.
|
|
|
|
Here's the above example URLconf, rewritten to use named groups::
|
|
|
|
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'),
|
|
)
|
|
|
|
This accomplishes exactly the same thing as the previous example, with one
|
|
subtle difference: The captured values are passed to view functions as keyword
|
|
arguments rather than positional arguments. For example:
|
|
|
|
* A request to ``/articles/2005/03/`` would call the function
|
|
``news.views.month_archive(request, year='2005', month='03')``, instead
|
|
of ``news.views.month_archive(request, '2005', '03')``.
|
|
|
|
* A request to ``/articles/2003/03/3/`` would call the function
|
|
``news.views.article_detail(request, year='2003', month='03', day='3')``.
|
|
|
|
In practice, this means your URLconfs are slightly more explicit and less prone
|
|
to argument-order bugs -- and you can reorder the arguments in your views'
|
|
function definitions. Of course, these benefits come at the cost of brevity;
|
|
some developers find the named-group syntax ugly and too verbose.
|
|
|
|
The matching/grouping algorithm
|
|
-------------------------------
|
|
|
|
Here's the algorithm the URLconf parser follows, with respect to named groups
|
|
vs. non-named groups in a regular expression:
|
|
|
|
If there are any named arguments, it will use those, ignoring non-named arguments.
|
|
Otherwise, it will pass all non-named arguments as positional arguments.
|
|
|
|
In both cases, it will pass any extra keyword arguments as keyword arguments.
|
|
See "Passing extra options to view functions" below.
|
|
|
|
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 ``http://www.example.com/myapp/``, the URLconf
|
|
will look for ``myapp/``.
|
|
|
|
In a request to ``http://www.example.com/myapp/?page=3``, the URLconf will look
|
|
for ``myapp/``.
|
|
|
|
The URLconf doesn't look at the request method. In other words, all request
|
|
methods -- ``POST``, ``GET``, ``HEAD``, etc. -- will be routed to the same
|
|
function for the same URL.
|
|
|
|
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:
|
|
|
|
patterns
|
|
--------
|
|
|
|
.. function:: patterns(prefix, pattern_description, ...)
|
|
|
|
A function that takes a prefix, and 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 [, optional name]])
|
|
|
|
...where ``optional dictionary`` and ``optional name`` are optional. (See
|
|
`Passing extra options to view functions`_ below.)
|
|
|
|
.. note::
|
|
Because `patterns()` is a function call, it accepts a maximum of 255
|
|
arguments (URL patterns, in this case). This is a limit for all Python
|
|
function calls. This is rarely a problem in practice, because you'll
|
|
typically structure your URL patterns modularly by using `include()`
|
|
sections. However, on the off-chance you do hit the 255-argument limit,
|
|
realize that `patterns()` returns a Python list, so you can split up the
|
|
construction of the list.
|
|
|
|
::
|
|
|
|
urlpatterns = patterns('',
|
|
...
|
|
)
|
|
urlpatterns += patterns('',
|
|
...
|
|
)
|
|
|
|
Python lists have unlimited size, so there's no limit to how many URL
|
|
patterns you can construct. The only limit is that you can only create 254
|
|
at a time (the 255th argument is the initial prefix argument).
|
|
|
|
url
|
|
---
|
|
|
|
.. versionadded:: 1.0
|
|
|
|
.. function:: url(regex, view, kwargs=None, name=None, prefix='')
|
|
|
|
You can use the ``url()`` function, instead of a tuple, as an argument to
|
|
``patterns()``. This is convenient if you want to specify a name without the
|
|
optional extra arguments dictionary. For example::
|
|
|
|
urlpatterns = patterns('',
|
|
url(r'^index/$', index_view, name="main-view"),
|
|
...
|
|
)
|
|
|
|
This function takes five arguments, most of which are optional::
|
|
|
|
url(regex, view, kwargs=None, name=None, prefix='')
|
|
|
|
See `Naming URL patterns`_ for why the ``name`` parameter is useful.
|
|
|
|
The ``prefix`` parameter has the same meaning as the first argument to
|
|
``patterns()`` and is only relevant when you're passing a string as the
|
|
``view`` parameter.
|
|
|
|
handler404
|
|
----------
|
|
|
|
.. data:: handler404
|
|
|
|
A callable, or 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.
|
|
|
|
.. versionchanged:: 1.2
|
|
Previous versions of Django only accepted strings representing import paths.
|
|
|
|
handler500
|
|
----------
|
|
|
|
.. data:: handler500
|
|
|
|
A callable, or 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.
|
|
|
|
.. versionchanged:: 1.2
|
|
Previous versions of Django only accepted strings representing import paths.
|
|
|
|
include
|
|
-------
|
|
|
|
.. function:: include(<module or pattern_list>)
|
|
|
|
A function that takes a full Python import path to another URLconf module that
|
|
should be "included" in this place.
|
|
|
|
.. versionadded:: 1.1
|
|
|
|
:func:`include` also accepts as an argument an iterable that returns URL
|
|
patterns.
|
|
|
|
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
|
|
URLconf line::
|
|
|
|
(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/$', 'blog.views.page'),
|
|
(r'^blog/page(?P<num>\d+)/$', 'blog.views.page'),
|
|
)
|
|
|
|
# View (in blog/views.py)
|
|
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 --
|
|
``blog.views.page`` -- 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.
|
|
|
|
Performance
|
|
===========
|
|
|
|
Each regular expression in a ``urlpatterns`` is compiled the first time it's
|
|
accessed. This makes the system blazingly fast.
|
|
|
|
The view prefix
|
|
===============
|
|
|
|
You can specify a common prefix in your ``patterns()`` call, to cut down on
|
|
code duplication.
|
|
|
|
Here's the example URLconf from the :ref:`Django overview <intro-overview>`::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^articles/(\d{4})/$', 'mysite.news.views.year_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/$', 'mysite.news.views.month_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.news.views.article_detail'),
|
|
)
|
|
|
|
In this example, each view has a common prefix -- ``'mysite.news.views'``.
|
|
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('mysite.news.views',
|
|
(r'^articles/(\d{4})/$', 'year_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/$', 'month_archive'),
|
|
(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'article_detail'),
|
|
)
|
|
|
|
Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
|
|
that in automatically.
|
|
|
|
Multiple view prefixes
|
|
----------------------
|
|
|
|
In practice, you'll probably end up mixing and matching views to the point
|
|
where the views in your ``urlpatterns`` won't have a common prefix. However,
|
|
you can still take advantage of the view prefix shortcut to remove duplication.
|
|
Just add multiple ``patterns()`` objects together, like this:
|
|
|
|
Old::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^$', 'django.views.generic.date_based.archive_index'),
|
|
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'django.views.generic.date_based.archive_month'),
|
|
(r'^tag/(?P<tag>\w+)/$', 'weblog.views.tag'),
|
|
)
|
|
|
|
New::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
urlpatterns = patterns('django.views.generic.date_based',
|
|
(r'^$', 'archive_index'),
|
|
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$','archive_month'),
|
|
)
|
|
|
|
urlpatterns += patterns('weblog.views',
|
|
(r'^tag/(?P<tag>\w+)/$', 'tag'),
|
|
)
|
|
|
|
Including 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 Web site`_ itself. It includes a
|
|
number of other URLconfs::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^weblog/', include('django_website.apps.blog.urls.blog')),
|
|
(r'^documentation/', include('django_website.apps.docs.urls.docs')),
|
|
(r'^comments/', include('django.contrib.comments.urls')),
|
|
)
|
|
|
|
Note that the regular expressions in this example don't have a ``$``
|
|
(end-of-string match character) but do include a trailing slash. Whenever
|
|
Django encounters ``include()``, it chops off whatever part of the URL matched
|
|
up to that point and sends the remaining string to the included URLconf for
|
|
further processing.
|
|
|
|
.. versionadded:: 1.1
|
|
|
|
Another possibility is to include additional URL patterns not by specifying the
|
|
URLconf Python module defining them as the `include`_ argument but by using
|
|
directly the pattern list as returned by `patterns`_ instead. For example::
|
|
|
|
from django.conf.urls.defaults import *
|
|
|
|
extra_patterns = patterns('',
|
|
url(r'reports/(?P<id>\d+)/$', 'credit.views.report', name='credit-reports'),
|
|
url(r'charge/$', 'credit.views.charge', name='credit-charge'),
|
|
)
|
|
|
|
urlpatterns = patterns('',
|
|
url(r'^$', 'apps.main.views.homepage', name='site-homepage'),
|
|
(r'^help/', include('apps.help.urls')),
|
|
(r'^credit/', include(extra_patterns)),
|
|
)
|
|
|
|
This approach can be seen in use when you deploy an instance of the Django
|
|
Admin application. The Django Admin is deployed as instances of a
|
|
:class:`AdminSite`; each :class:`AdminSite` instance has an attribute
|
|
``urls`` that returns the url patterns available to that instance. It is this
|
|
attribute that you ``include()`` into your projects ``urlpatterns`` when you
|
|
deploy the admin instance.
|
|
|
|
.. _`Django Web site`: http://www.djangoproject.com/
|
|
|
|
Captured parameters
|
|
-------------------
|
|
|
|
An included URLconf receives any captured parameters from parent URLconfs, so
|
|
the following example is valid::
|
|
|
|
# In settings/urls/main.py
|
|
urlpatterns = patterns('',
|
|
(r'^(?P<username>\w+)/blog/', include('foo.urls.blog')),
|
|
)
|
|
|
|
# In foo/urls/blog.py
|
|
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.
|
|
|
|
.. _topics-http-defining-url-namespaces:
|
|
|
|
Defining URL Namespaces
|
|
-----------------------
|
|
|
|
When you need to deploy multiple instances of a single application, it can be
|
|
helpful to be able to differentiate between instances. This is especially
|
|
important when using :ref:`named URL patterns <naming-url-patterns>`, since
|
|
multiple instances of a single application will share named URLs. Namespaces
|
|
provide a way to tell these named URLs apart.
|
|
|
|
A URL namespace comes in two parts, both of which are strings:
|
|
|
|
* An **application namespace**. This describes the name of the application
|
|
that is being deployed. Every instance of a single application will have
|
|
the same application namespace. For example, Django's admin application
|
|
has the somewhat predictable application namespace of ``admin``.
|
|
|
|
* An **instance namespace**. This identifies a specific instance of an
|
|
application. Instance namespaces should be unique across your entire
|
|
project. However, an instance namespace can be the same as the
|
|
application namespace. This is used to specify a default instance of an
|
|
application. For example, the default Django Admin instance has an
|
|
instance namespace of ``admin``.
|
|
|
|
URL Namespaces can be specified in two ways.
|
|
|
|
Firstly, you can provide the application and instance namespace as arguments
|
|
to ``include()`` when you construct your URL patterns. For example,::
|
|
|
|
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
|
|
|
|
This will include the URLs defined in ``apps.help.urls`` into the application
|
|
namespace ``bar``, with the instance namespace ``foo``.
|
|
|
|
Secondly, you can include an object that contains embedded namespace data. If
|
|
you ``include()`` a ``patterns`` object, that object will be added to the
|
|
global namespace. However, you can also ``include()`` an object that contains
|
|
a 3-tuple containing::
|
|
|
|
(<patterns object>, <application namespace>, <instance namespace>)
|
|
|
|
This will include the nominated URL patterns into the given application and
|
|
instance namespace. For example, the ``urls`` attribute of Django's
|
|
:class:`AdminSite` object returns a 3-tuple that contains all the patterns in
|
|
an admin site, plus the name of the admin instance, and the application
|
|
namespace ``admin``.
|
|
|
|
Once you have defined namespaced URLs, you can reverse them. For details on
|
|
reversing namespaced urls, see the documentation on :ref:`reversing namespaced
|
|
URLs <topics-http-reversing-url-namespaces>`.
|
|
|
|
Passing extra options to view functions
|
|
=======================================
|
|
|
|
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('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 :ref:`generic views <ref-generic-views>` and in the
|
|
:ref:`syndication framework <ref-contrib-syndication>` to pass metadata and
|
|
options to views.
|
|
|
|
.. admonition:: Dealing with conflicts
|
|
|
|
It's possible to have a URL pattern which captures named keyword arguments,
|
|
and also passes arguments with the same names in its dictionary of extra
|
|
arguments. When this happens, the arguments in the dictionary will be used
|
|
instead of the arguments captured in the URL.
|
|
|
|
Passing extra options to ``include()``
|
|
--------------------------------------
|
|
|
|
Similarly, you can pass extra options to ``include()``. When you pass extra
|
|
options to ``include()``, *each* line in the included URLconf will be passed
|
|
the extra options.
|
|
|
|
For example, these two URLconf sets are functionally identical:
|
|
|
|
Set one::
|
|
|
|
# main.py
|
|
urlpatterns = patterns('',
|
|
(r'^blog/', include('inner'), {'blogid': 3}),
|
|
)
|
|
|
|
# inner.py
|
|
urlpatterns = patterns('',
|
|
(r'^archive/$', 'mysite.views.archive'),
|
|
(r'^about/$', 'mysite.views.about'),
|
|
)
|
|
|
|
Set two::
|
|
|
|
# main.py
|
|
urlpatterns = patterns('',
|
|
(r'^blog/', include('inner')),
|
|
)
|
|
|
|
# inner.py
|
|
urlpatterns = patterns('',
|
|
(r'^archive/$', 'mysite.views.archive', {'blogid': 3}),
|
|
(r'^about/$', 'mysite.views.about', {'blogid': 3}),
|
|
)
|
|
|
|
Note that extra options will *always* be passed to *every* line in the included
|
|
URLconf, regardless of whether the line's view actually accepts those options
|
|
as valid. For this reason, this technique is only useful if you're certain that
|
|
every view in the included URLconf accepts the extra options you're passing.
|
|
|
|
Passing callable objects instead of strings
|
|
===========================================
|
|
|
|
Some developers find it more natural to pass the actual Python function object
|
|
rather than a string containing the path to its module. This alternative is
|
|
supported -- you can pass any callable object as the view.
|
|
|
|
For example, given this URLconf in "string" notation::
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^archive/$', 'mysite.views.archive'),
|
|
(r'^about/$', 'mysite.views.about'),
|
|
(r'^contact/$', 'mysite.views.contact'),
|
|
)
|
|
|
|
You can accomplish the same thing by passing objects rather than strings. Just
|
|
be sure to import the objects::
|
|
|
|
from mysite.views import archive, about, contact
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^archive/$', archive),
|
|
(r'^about/$', about),
|
|
(r'^contact/$', contact),
|
|
)
|
|
|
|
The following example is functionally identical. It's just a bit more compact
|
|
because it imports the module that contains the views, rather than importing
|
|
each view individually::
|
|
|
|
from mysite import views
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^archive/$', views.archive),
|
|
(r'^about/$', views.about),
|
|
(r'^contact/$', views.contact),
|
|
)
|
|
|
|
The style you use is up to you.
|
|
|
|
Note that if you use this technique -- passing objects rather than strings --
|
|
the view prefix (as explained in "The view prefix" above) will have no effect.
|
|
|
|
.. _naming-url-patterns:
|
|
|
|
Naming URL patterns
|
|
===================
|
|
|
|
.. versionadded:: 1.0
|
|
|
|
It's fairly common to use the same view function in multiple URL patterns in
|
|
your URLconf. For example, these two URL patterns both point to the ``archive``
|
|
view::
|
|
|
|
urlpatterns = patterns('',
|
|
(r'^archive/(\d{4})/$', archive),
|
|
(r'^archive-summary/(\d{4})/$', archive, {'summary': True}),
|
|
)
|
|
|
|
This is completely valid, but it leads to problems when you try to do reverse
|
|
URL matching (through the ``permalink()`` decorator or the :ttag:`url` template
|
|
tag). Continuing this example, if you wanted to retrieve the URL for the
|
|
``archive`` view, Django's reverse URL matcher would get confused, because *two*
|
|
URLpatterns point at that view.
|
|
|
|
To solve this problem, Django supports **named URL patterns**. That is, you can
|
|
give a name to a URL pattern in order to distinguish it from other patterns
|
|
using the same view and parameters. Then, you can use this name in reverse URL
|
|
matching.
|
|
|
|
Here's the above example, rewritten to use named URL patterns::
|
|
|
|
urlpatterns = patterns('',
|
|
url(r'^archive/(\d{4})/$', archive, name="full-archive"),
|
|
url(r'^archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"),
|
|
)
|
|
|
|
With these names in place (``full-archive`` and ``arch-summary``), you can
|
|
target each pattern individually by using its name:
|
|
|
|
.. code-block:: html+django
|
|
|
|
{% url arch-summary 1945 %}
|
|
{% url full-archive 2007 %}
|
|
|
|
Even though both URL patterns refer to the ``archive`` view here, using the
|
|
``name`` parameter to ``url()`` allows you to tell them apart in templates.
|
|
|
|
The string used for the URL name can contain any characters you like. You are
|
|
not restricted to valid Python names.
|
|
|
|
.. note::
|
|
|
|
When you name your URL patterns, make sure you use names that are unlikely
|
|
to clash with any other application's choice of names. If you call your URL
|
|
pattern ``comment``, and another application does the same thing, there's
|
|
no guarantee which URL will be inserted into your template when you use
|
|
this name.
|
|
|
|
Putting a prefix on your URL names, perhaps derived from the application
|
|
name, will decrease the chances of collision. We recommend something like
|
|
``myapp-comment`` instead of ``comment``.
|
|
|
|
.. _topics-http-reversing-url-namespaces:
|
|
|
|
URL namespaces
|
|
--------------
|
|
|
|
.. versionadded:: 1.1
|
|
|
|
Namespaced URLs are specified using the ``:`` operator. For example, the main
|
|
index page of the admin application is referenced using ``admin:index``. This
|
|
indicates a namespace of ``admin``, and a named URL of ``index``.
|
|
|
|
Namespaces can also be nested. The named URL ``foo:bar:whiz`` would look for
|
|
a pattern named ``whiz`` in the namespace ``bar`` that is itself defined within
|
|
the top-level namespace ``foo``.
|
|
|
|
When given a namespaced URL (e.g. ``myapp:index``) to resolve, Django splits
|
|
the fully qualified name into parts, and then tries the following lookup:
|
|
|
|
1. First, Django looks for a matching application namespace (in this
|
|
example, ``myapp``). This will yield a list of instances of that
|
|
application.
|
|
|
|
2. If there is a *current* application defined, Django finds and returns
|
|
the URL resolver for that instance. The *current* application can be
|
|
specified as an attribute on the template context - applications that
|
|
expect to have multiple deployments should set the ``current_app``
|
|
attribute on any ``Context`` or ``RequestContext`` that is used to
|
|
render a template.
|
|
|
|
The current application can also be specified manually as an argument
|
|
to the :func:`reverse()` function.
|
|
|
|
3. If there is no current application. Django looks for a default
|
|
application instance. The default application instance is the instance
|
|
that has an instance namespace matching the application namespace (in
|
|
this example, an instance of the ``myapp`` called ``myapp``).
|
|
|
|
4. If there is no default application instance, Django will pick the last
|
|
deployed instance of the application, whatever its instance name may be.
|
|
|
|
5. If the provided namespace doesn't match an application namespace in
|
|
step 1, Django will attempt a direct lookup of the namespace as an
|
|
instance namespace.
|
|
|
|
If there are nested namespaces, these steps are repeated for each part of the
|
|
namespace until only the view name is unresolved. The view name will then be
|
|
resolved into a URL in the namespace that has been found.
|
|
|
|
To show this resolution strategy in action, consider an example of two instances
|
|
of ``myapp``: one called ``foo``, and one called ``bar``. ``myapp`` has a main
|
|
index page with a URL named `index`. Using this setup, the following lookups are
|
|
possible:
|
|
|
|
* If one of the instances is current - say, if we were rendering a utility page
|
|
in the instance ``bar`` - ``myapp:index`` will resolve to the index page of
|
|
the instance ``bar``.
|
|
|
|
* If there is no current instance - say, if we were rendering a page
|
|
somewhere else on the site - ``myapp:index`` will resolve to the last
|
|
registered instance of ``myapp``. Since there is no default instance,
|
|
the last instance of ``myapp`` that is registered will be used. This could
|
|
be ``foo`` or ``bar``, depending on the order they are introduced into the
|
|
urlpatterns of the project.
|
|
|
|
* ``foo:index`` will always resolve to the index page of the instance ``foo``.
|
|
|
|
If there was also a default instance - i.e., an instance named `myapp` - the
|
|
following would happen:
|
|
|
|
* If one of the instances is current - say, if we were rendering a utility page
|
|
in the instance ``bar`` - ``myapp:index`` will resolve to the index page of
|
|
the instance ``bar``.
|
|
|
|
* If there is no current instance - say, if we were rendering a page somewhere
|
|
else on the site - ``myapp:index`` will resolve to the index page of the
|
|
default instance.
|
|
|
|
* ``foo:index`` will again resolve to the index page of the instance ``foo``.
|
|
|
|
|
|
Utility methods
|
|
===============
|
|
|
|
reverse()
|
|
---------
|
|
|
|
If you need to use something similar to the :ttag:`url` template tag in
|
|
your code, Django provides the following method (in the
|
|
``django.core.urlresolvers`` module):
|
|
|
|
.. function:: reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None)
|
|
|
|
``viewname`` is either the function name (either a function reference, or the
|
|
string version of the name, if you used that form in ``urlpatterns``) or the
|
|
`URL pattern name`_. Normally, you won't need to worry about the
|
|
``urlconf`` parameter and will only pass in the positional and keyword
|
|
arguments to use in the URL matching. For example::
|
|
|
|
from django.core.urlresolvers import reverse
|
|
|
|
def myview(request):
|
|
return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
|
|
|
|
.. _URL pattern name: `Naming URL patterns`_
|
|
|
|
The ``reverse()`` function can reverse a large variety of regular expression
|
|
patterns for URLs, but not every possible one. The main restriction at the
|
|
moment is that the pattern cannot contain alternative choices using the
|
|
vertical bar (``"|"``) character. You can quite happily use such patterns for
|
|
matching against incoming URLs and sending them off to views, but you cannot
|
|
reverse such patterns.
|
|
|
|
.. versionadded:: 1.1
|
|
|
|
The ``current_app`` argument allows you to provide a hint to the resolver
|
|
indicating the application to which the currently executing view belongs.
|
|
This ``current_app`` argument is used as a hint to resolve application
|
|
namespaces into URLs on specific application instances, according to the
|
|
:ref:`namespaced URL resolution strategy <topics-http-reversing-url-namespaces>`.
|
|
|
|
.. admonition:: Make sure your views are all correct
|
|
|
|
As part of working out which URL names map to which patterns, the
|
|
``reverse()`` function has to import all of your URLconf files and examine
|
|
the name of each view. This involves importing each view function. If
|
|
there are *any* errors whilst importing any of your view functions, it
|
|
will cause ``reverse()`` to raise an error, even if that view function is
|
|
not the one you are trying to reverse.
|
|
|
|
Make sure that any views you reference in your URLconf files exist and can
|
|
be imported correctly. Do not include lines that reference views you
|
|
haven't written yet, because those views will not be importable.
|
|
|
|
resolve()
|
|
---------
|
|
|
|
The :func:`django.core.urlresolvers.resolve` function can be used for
|
|
resolving URL paths to the corresponding view functions. It has the
|
|
following signature:
|
|
|
|
.. function:: resolve(path, urlconf=None)
|
|
|
|
``path`` is the URL path you want to resolve. As with
|
|
:func:`~django.core.urlresolvers.reverse`, you don't need to
|
|
worry about the ``urlconf`` parameter. The function returns a
|
|
:class:`django.core.urlresolvers.ResolverMatch` object that allows you
|
|
to access various meta-data about the resolved URL.
|
|
|
|
.. class:: ResolverMatch()
|
|
|
|
.. attribute:: ResolverMatch.func
|
|
|
|
The view function that would be used to serve the URL
|
|
|
|
.. attribute:: ResolverMatch.args
|
|
|
|
The arguments that would be passed to the view function, as
|
|
parsed from the URL.
|
|
|
|
.. attribute:: ResolverMatch.kwargs
|
|
|
|
The keyword arguments that would be passed to the view
|
|
function, as parsed from the URL.
|
|
|
|
.. attribute:: ResolverMatch.url_name
|
|
|
|
The name of the URL pattern that matches the URL.
|
|
|
|
.. attribute:: ResolverMatch.app_name
|
|
|
|
The application namespace for the URL pattern that matches the
|
|
URL.
|
|
|
|
.. attribute:: ResolverMatch.namespace
|
|
|
|
The instance namespace for the URL pattern that matches the
|
|
URL.
|
|
|
|
.. attribute:: ResolverMatch.namespaces
|
|
|
|
The list of individual namespace components in the full
|
|
instance namespace for the URL pattern that matches the URL.
|
|
i.e., if the namespace is ``foo:bar``, then namespaces will be
|
|
``[`foo`, `bar`]``.
|
|
|
|
A :class:`~django.core.urlresolvers.ResolverMatch` object can then be
|
|
interrogated to provide information about the URL pattern that matches
|
|
a URL::
|
|
|
|
# Resolve a URL
|
|
match = resolve('/some/path/')
|
|
# Print the URL pattern that matches the URL
|
|
print match.url_name
|
|
|
|
A :class:`~django.core.urlresolvers.ResolverMatch` object can also be
|
|
assigned to a triple::
|
|
|
|
func, args, kwargs = resolve('/some/path/')
|
|
|
|
.. versionchanged:: 1.3
|
|
Triple-assignment exists for backwards-compatibility. Prior to
|
|
Django 1.3, :func:`~django.core.urlresolvers.resolve` returned a
|
|
triple containing (view function, arguments, keyword arguments);
|
|
the :class:`~django.core.urlresolvers.ResolverMatch` object (as
|
|
well as the namespace and pattern information it provides) is not
|
|
available in earlier Django releases.
|
|
|
|
One possible use of :func:`~django.core.urlresolvers.resolve` would be
|
|
to testing if a view would raise a ``Http404`` error before
|
|
redirecting to it::
|
|
|
|
from urlparse import urlparse
|
|
from django.core.urlresolvers import resolve
|
|
from django.http import HttpResponseRedirect, Http404
|
|
|
|
def myview(request):
|
|
next = request.META.get('HTTP_REFERER', None) or '/'
|
|
response = HttpResponseRedirect(next)
|
|
|
|
# modify the request and response as required, e.g. change locale
|
|
# and set corresponding locale cookie
|
|
|
|
view, args, kwargs = resolve(urlparse(next)[2])
|
|
kwargs['request'] = request
|
|
try:
|
|
view(*args, **kwargs)
|
|
except Http404:
|
|
return HttpResponseRedirect('/')
|
|
return response
|
|
|
|
|
|
permalink()
|
|
-----------
|
|
|
|
The :func:`django.db.models.permalink` decorator is useful for writing short
|
|
methods that return a full URL path. For example, a model's
|
|
``get_absolute_url()`` method. See :func:`django.db.models.permalink` for more.
|