Browse Source

Added section about URL reversion to URL mapper document.

Ramiro Morales 12 years ago
parent
commit
ec1aad1671

+ 1 - 1
docs/ref/contrib/formtools/form-wizard.txt

@@ -226,7 +226,7 @@ Hooking the wizard into a URLconf
 ---------------------------------
 
 Finally, we need to specify which forms to use in the wizard, and then
-deploy the new :class:`WizardView` object at an URL in the ``urls.py``. The
+deploy the new :class:`WizardView` object at a URL in the ``urls.py``. The
 wizard's :meth:`as_view` method takes a list of your
 :class:`~django.forms.Form` classes as an argument during instantiation::
 

+ 9 - 3
docs/ref/models/instances.txt

@@ -494,12 +494,16 @@ defined. If it makes sense for your model's instances to each have a unique
 URL, you should define ``get_absolute_url()``.
 
 It's good practice to use ``get_absolute_url()`` in templates, instead of
-hard-coding your objects' URLs. For example, this template code is bad::
+hard-coding your objects' URLs. For example, this template code is bad:
+
+.. code-block:: html+django
 
     <!-- BAD template code. Avoid! -->
     <a href="/people/{{ object.id }}/">{{ object.name }}</a>
 
-This template code is much better::
+This template code is much better:
+
+.. code-block:: html+django
 
     <a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
 
@@ -535,7 +539,9 @@ pattern name) and a list of position or keyword arguments and uses the URLconf
 patterns to construct the correct, full URL. It returns a string for the
 correct URL, with all parameters substituted in the correct positions.
 
-The ``permalink`` decorator is a Python-level equivalent to the :ttag:`url` template tag and a high-level wrapper for the :func:`django.core.urlresolvers.reverse()` function.
+The ``permalink`` decorator is a Python-level equivalent to the :ttag:`url`
+template tag and a high-level wrapper for the
+:func:`django.core.urlresolvers.reverse()` function.
 
 An example should make it clear how to use ``permalink()``. Suppose your URLconf
 contains a line such as::

+ 1 - 1
docs/ref/templates/builtins.txt

@@ -997,7 +997,7 @@ refer to the name of the pattern in the ``url`` tag instead of using the
 path to the view.
 
 Note that if the URL you're reversing doesn't exist, you'll get an
-:exc:`^django.core.urlresolvers.NoReverseMatch` exception raised, which will
+:exc:`~django.core.urlresolvers.NoReverseMatch` exception raised, which will
 cause your site to display an error page.
 
 If you'd like to retrieve a URL without displaying it, you can use a slightly

+ 7 - 9
docs/ref/urlresolvers.txt

@@ -8,8 +8,7 @@ reverse()
 ---------
 
 If you need to use something similar to the :ttag:`url` template tag in
-your code, Django provides the following function (in the
-:mod:`django.core.urlresolvers` module):
+your code, Django provides the following function:
 
 .. function:: reverse(viewname, [urlconf=None, args=None, kwargs=None, current_app=None])
 
@@ -59,15 +58,15 @@ You can use ``kwargs`` instead of ``args``. For example::
 
 .. note::
 
-    The string returned by :meth:`~django.core.urlresolvers.reverse` is already
+    The string returned by ``reverse()`` is already
     :ref:`urlquoted <uri-and-iri-handling>`. For example::
 
         >>> reverse('cities', args=[u'Orléans'])
         '.../Orl%C3%A9ans/'
 
     Applying further encoding (such as :meth:`~django.utils.http.urlquote` or
-    ``urllib.quote``) to the output of :meth:`~django.core.urlresolvers.reverse`
-    may produce undesirable results.
+    ``urllib.quote``) to the output of ``reverse()`` may produce undesirable
+    results.
 
 reverse_lazy()
 --------------
@@ -94,9 +93,8 @@ URLConf is loaded. Some common cases where this function is necessary are:
 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:
+The ``resolve()`` function can be used for resolving URL paths to the
+corresponding view functions. It has the following signature:
 
 .. function:: resolve(path, urlconf=None)
 
@@ -184,7 +182,7 @@ whether a view would raise a ``Http404`` error before redirecting to it::
 permalink()
 -----------
 
-The :func:`django.db.models.permalink` decorator is useful for writing short
+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.
 

+ 113 - 6
docs/topics/http/urls.txt

@@ -421,9 +421,9 @@ options to views.
 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.
+Similarly, you can pass extra options to :func:`~django.conf.urls.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:
 
@@ -510,6 +510,103 @@ imported::
         (r'^myview/$', ClassBasedView.as_view()),
     )
 
+Reverse resolution of URLs
+==========================
+
+A common need when working on a Django project is the possibility to obtain URLs
+in their final forms either for embedding in generated content (views and assets
+URLs, URLs shown to the user, etc.) or for handling of the navigation flow on
+the server side (redirections, etc.)
+
+It is strongly desirable not having to hard-code these URLs (a laborious,
+non-scalable and error-prone strategy) or having to devise ad-hoc mechanisms for
+generating URLs that are parallel to the design described by the URLconf and as
+such in danger of producing stale URLs at some point.
+
+In other words, what's needed is a DRY mechanism. Among other advantages it
+would allow evolution of the URL design without having to go all over the
+project source code to search and replace outdated URLs.
+
+The piece of information we have available as a starting point to get a URL is
+an identification (e.g. the name) of the view in charge of handling it, other
+pieces of information that necessarily must participate in the lookup of the
+right URL are the types (positional, keyword) and values of the view arguments.
+
+Django provides a solution such that the URL mapper is the only repository of
+the URL design. You feed it with your URLconf and then it can be used in both
+directions:
+
+* Starting with a URL requested by the user/browser, it calls the right Django
+  view providing any arguments it might need with their values as extracted from
+  the URL.
+
+* Starting with the identification of the corresponding Django view plus the
+  values of arguments that would be passed to it, obtain the associated URL.
+
+The first one is the usage we've been discussing in the previous sections. The
+second one is what is known as *reverse resolution of URLs*, *reverse URL
+matching*, *reverse URL lookup*, or simply *URL reversing*.
+
+Django provides tools for performing URL reversing that match the different
+layers where URLs are needed:
+
+* In templates: Using the :ttag:`url` template tag.
+
+* In Python code: Using the :func:`django.core.urlresolvers.reverse()`
+  function.
+
+* In higher level code related to handling of URLs of Django model instances:
+  The :meth:`django.db.models.Model.get_absolute_url()` method and the
+  :func:`django.db.models.permalink` decorator.
+
+Examples
+--------
+
+Consider again this URLconf entry::
+
+    from django.conf.urls import patterns, url
+
+    urlpatterns = patterns('',
+	#...
+        url(r'^articles/(\d{4})/$', 'news.views.year_archive'),
+	#...
+    )
+
+According to this design, the URL for the archive corresponding to year *nnnn*
+is ``/articles/nnnn/``.
+
+You can obtain these in template code by using:
+
+.. code-block:: html+django
+
+    <a href="{% url 'news.views.year_archive' 2012 %}">2012 Archive</a>
+    {# Or with the year in a template context variable: #}
+    <ul>
+    {% for yearvar in year_list %}
+    <li><a href="{% url 'news.views.year_archive' yearvar %}">{{ yearvar }} Archive</a></li>
+    {% endfor %}
+    </ul>
+
+Or in Python code::
+
+    from django.core.urlresolvers import reverse
+    from django.http import HttpResponseRedirect
+
+    def redirect_to_year(request):
+        # ...
+        year = 2006
+        # ...
+        return HttpResponseRedirect(reverse('new.views.year_archive', args=(year,)))
+
+If, for some reason, it was decided that the URL where content for yearly
+article archives are published at should be changed then you would only need to
+change the entry in the URLconf.
+
+In some scenarios where views are of a generic nature, a many-to-one
+relationship might exist between URLs and views. For these cases the view name
+isn't a good enough identificator for it when it comes the time of reversing
+URLs. Read the next section to know about the solution Django provides for this.
+
 .. _naming-url-patterns:
 
 Naming URL patterns
@@ -689,9 +786,10 @@ URL namespaces and included URLconfs
 
 URL namespaces of included URLconfs can be specified in two ways.
 
-Firstly, you can provide the application and :term:`instance namespace` as
-arguments to :func:`django.conf.urls.include()` when you construct your URL
-patterns. For example,::
+Firstly, you can provide the :term:`application <application namespace>` and
+:term:`instance <instance namespace>` namespaces as arguments to
+:func:`django.conf.urls.include()` when you construct your URL patterns. For
+example,::
 
     (r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
 
@@ -706,6 +804,15 @@ However, you can also ``include()`` a 3-tuple containing::
 
     (<patterns object>, <application namespace>, <instance namespace>)
 
+For example::
+
+    help_patterns = patterns('',
+        url(r'^basic/$', 'apps.help.views.views.basic'),
+        url(r'^advanced/$', 'apps.help.views.views.advanced'),
+    )
+
+    (r'^help/', include(help_patterns, 'bar', 'foo')),
+
 This will include the nominated URL patterns into the given application and
 instance namespace.
 

+ 1 - 1
docs/topics/testing.txt

@@ -769,7 +769,7 @@ Use the ``django.test.client.Client`` class to make requests.
         and a ``redirect_chain`` attribute will be set in the response object
         containing tuples of the intermediate urls and status codes.
 
-        If you had an url ``/redirect_me/`` that redirected to ``/next/``, that
+        If you had a URL ``/redirect_me/`` that redirected to ``/next/``, that
         redirected to ``/final/``, this is what you'd see::
 
             >>> response = c.get('/redirect_me/', follow=True)