Slightly rewrite @permalink and get_absolute_url() documentation.
Part 2 of the model instance documentation changes. Slightly tidied up get_absolute_url() and @permalink documentation to collapse some of the earlier versions into a preferred learning order. I'm still not amazingly happy with this, but larger rewrites are needed to the URLconf stuff across a few files before I can get it into the most natural order, I suspect. That's a slightly longer-term project. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16702 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a0eb58e90b
commit
77189afb7f
|
@ -414,60 +414,82 @@ using ``__str__()`` like this::
|
||||||
.. method:: Model.get_absolute_url()
|
.. method:: Model.get_absolute_url()
|
||||||
|
|
||||||
Define a ``get_absolute_url()`` method to tell Django how to calculate the
|
Define a ``get_absolute_url()`` method to tell Django how to calculate the
|
||||||
canonical URL for an object. For example::
|
canonical URL for an object. To callers, this method should appear to return a
|
||||||
|
string that can be used to refer to the object over HTTP.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
def get_absolute_url(self):
|
def get_absolute_url(self):
|
||||||
return "/people/%i/" % self.id
|
return "/people/%i/" % self.id
|
||||||
|
|
||||||
Django uses this in its admin interface. If an object defines
|
(Whilst this code is correct and simple, it may not be the most portable way to
|
||||||
``get_absolute_url()``, the object-editing page will have a "View on site"
|
write this kind of method. The :func:`permalink() decorator <permalink>`,
|
||||||
link that will jump you directly to the object's public view, according to
|
documented below, is usually the best approach and you should read that section
|
||||||
|
before diving into code implementation.)
|
||||||
|
|
||||||
|
One place Django uses ``get_absolute_url()`` is in the admin app. If an object
|
||||||
|
defines this method, the object-editing page will have a "View on site" link
|
||||||
|
that will jump you directly to the object's public view, as given by
|
||||||
``get_absolute_url()``.
|
``get_absolute_url()``.
|
||||||
|
|
||||||
Also, a couple of other bits of Django, such as the :doc:`syndication feed
|
Similarly, a couple of other bits of Django, such as the :doc:`syndication feed
|
||||||
framework </ref/contrib/syndication>`, use ``get_absolute_url()`` as a
|
framework </ref/contrib/syndication>`, use ``get_absolute_url()`` when it is
|
||||||
convenience to reward people who've defined the method.
|
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
|
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::
|
||||||
|
|
||||||
|
<!-- BAD template code. Avoid! -->
|
||||||
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
|
<a href="/people/{{ object.id }}/">{{ object.name }}</a>
|
||||||
|
|
||||||
But this template code is good::
|
This template code is much better::
|
||||||
|
|
||||||
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
|
||||||
|
|
||||||
|
The logic here is that if you change the URL structure of your objects, even
|
||||||
|
for something simple such as correcting a spelling error, you don't want to
|
||||||
|
have to track down every place that the URL might be created. Specify it once,
|
||||||
|
in ``get_absolute_url()`` and have all your other code call that one place.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
The string you return from ``get_absolute_url()`` must contain only ASCII
|
The string you return from ``get_absolute_url()`` **must** contain only
|
||||||
characters (required by the URI spec, `RFC 2396`_) that have been
|
ASCII characters (required by the URI specfication, `RFC 2396`_) and be
|
||||||
URL-encoded, if necessary. Code and templates using ``get_absolute_url()``
|
URL-encoded, if necessary.
|
||||||
should be able to use the result directly without needing to do any
|
|
||||||
further processing. You may wish to use the
|
Code and templates calling ``get_absolute_url()`` should be able to use the
|
||||||
|
result directly without any further processing. You may wish to use the
|
||||||
``django.utils.encoding.iri_to_uri()`` function to help with this if you
|
``django.utils.encoding.iri_to_uri()`` function to help with this if you
|
||||||
are using unicode strings a lot.
|
are using unicode strings containing characters outside the ASCII range at
|
||||||
|
all.
|
||||||
|
|
||||||
.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt
|
.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt
|
||||||
|
|
||||||
The ``permalink`` decorator
|
The ``permalink`` decorator
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The problem with the way we wrote ``get_absolute_url()`` above is that it
|
The way we wrote ``get_absolute_url()`` above is a slightly violation of the
|
||||||
slightly violates the DRY principle: the URL for this object is defined both
|
DRY principle: the URL for this object is defined both in the URLconf file and
|
||||||
in the URLconf file and in the model.
|
in the model.
|
||||||
|
|
||||||
You can further decouple your models from the URLconf using the ``permalink``
|
You can decouple your models from the URLconf using the ``permalink`` decorator:
|
||||||
decorator:
|
|
||||||
|
|
||||||
.. function:: permalink()
|
.. function:: permalink()
|
||||||
|
|
||||||
This decorator is passed the view function, a list of positional parameters and
|
This decorator takes the name of a URL pattern (either a view name or a URL
|
||||||
(optionally) a dictionary of named parameters. Django then works out the correct
|
pattern name) and a list of position or keyword arguments and uses the URLconf
|
||||||
full URL path using the URLconf, substituting the parameters you have given into
|
patterns to construct the correct, full URL. It returns a string for the
|
||||||
the URL. For example, if your URLconf contained a line such as::
|
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.
|
||||||
|
|
||||||
|
An example should make it clear how to use ``permalink()``. Suppose your URLconf
|
||||||
|
contains a line such as::
|
||||||
|
|
||||||
(r'^people/(\d+)/$', 'people.views.details'),
|
(r'^people/(\d+)/$', 'people.views.details'),
|
||||||
|
|
||||||
...your model could have a ``get_absolute_url`` method that looked like this::
|
...your model could have a :meth:`~django.db.models.Model.get_absolute_url()`
|
||||||
|
method that looked like this::
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -491,26 +513,22 @@ Similarly, if you had a URLconf entry that looked like::
|
||||||
Notice that we specify an empty sequence for the second parameter in this case,
|
Notice that we specify an empty sequence for the second parameter in this case,
|
||||||
because we only want to pass keyword parameters, not positional ones.
|
because we only want to pass keyword parameters, not positional ones.
|
||||||
|
|
||||||
In this way, you're tying the model's absolute path to the view that is used
|
In this way, you're associating the model's absolute path with the view that is
|
||||||
to display it, without repeating the URL information anywhere. You can still
|
used to display it, without repeating the view's URL information anywhere. You
|
||||||
use the ``get_absolute_url`` method in templates, as before.
|
can still use the :meth:`~django.db.models.Model.get_absolute_url()` method in
|
||||||
|
templates, as before.
|
||||||
|
|
||||||
In some cases, such as the use of generic views or the re-use of
|
In some cases, such as the use of generic views or the re-use of custom views
|
||||||
custom views for multiple models, specifying the view function may
|
for multiple models, specifying the view function may confuse the reverse URL
|
||||||
confuse the reverse URL matcher (because multiple patterns point to
|
matcher (because multiple patterns point to the same view). For that case,
|
||||||
the same view).
|
Django has :ref:`named URL patterns <naming-url-patterns>`. Using a named URL
|
||||||
|
pattern, it's possible to give a name to a pattern, and then reference the name
|
||||||
For that problem, Django has **named URL patterns**. Using a named
|
rather than the view function. A named URL pattern is defined by replacing the
|
||||||
URL pattern, it's possible to give a name to a pattern, and then
|
pattern tuple by a call to the ``url`` function)::
|
||||||
reference the name rather than the view function. A named URL
|
|
||||||
pattern is defined by replacing the pattern tuple by a call to
|
|
||||||
the ``url`` function)::
|
|
||||||
|
|
||||||
from django.conf.urls.defaults import *
|
from django.conf.urls.defaults import *
|
||||||
|
|
||||||
url(r'^people/(\d+)/$',
|
url(r'^people/(\d+)/$', 'blog_views.generic_detail', name='people_view'),
|
||||||
'django.views.generic.list_detail.object_detail',
|
|
||||||
name='people_view'),
|
|
||||||
|
|
||||||
...and then using that name to perform the reverse URL resolution instead
|
...and then using that name to perform the reverse URL resolution instead
|
||||||
of the view name::
|
of the view name::
|
||||||
|
|
Loading…
Reference in New Issue