[1.5.X] Fixed #18974 - Warned against using models.permalink

Thanks dstufft for the draft patch.

Backport of 0e3690d230 from master
This commit is contained in:
Tim Graham 2012-11-20 07:15:16 -05:00
parent b9f9bc9a17
commit 42fa51c002
5 changed files with 43 additions and 40 deletions

View File

@ -482,9 +482,13 @@ For example::
return "/people/%i/" % self.id
(Whilst this code is correct and simple, it may not be the most portable way to
write this kind of method. The :func:`permalink() decorator <permalink>`,
documented below, is usually the best approach and you should read that section
before diving into code implementation.)
write this kind of method. The :func:`~django.core.urlresolvers.reverse`
function is usually the best approach.)
For example::
def get_absolute_url(self):
return reverse('people.views.details', args=[str(self.id)])
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
@ -529,11 +533,19 @@ in ``get_absolute_url()`` and have all your other code call that one place.
The ``permalink`` decorator
~~~~~~~~~~~~~~~~~~~~~~~~~~~
The way we wrote ``get_absolute_url()`` above is a slightly violation of the
DRY principle: the URL for this object is defined both in the URLconf file and
in the model.
.. warning::
You can decouple your models from the URLconf using the ``permalink`` decorator:
The ``permalink`` decorator is no longer recommended. You should use
:func:`~django.core.urlresolvers.reverse` in the body of your
``get_absolute_url`` method instead.
In early versions of Django, there wasn't an easy way to use URLs defined in
URLconf file inside :meth:`~django.db.models.Model.get_absolute_url`. That
meant you would need to define the URL both in URLConf and
:meth:`~django.db.models.Model.get_absolute_url`. The ``permalink`` decorator
was added to overcome this DRY principle violation. However, since the
introduction of :func:`~django.core.urlresolvers.reverse` there is no
reason to use ``permalink`` any more.
.. function:: permalink()
@ -544,14 +556,14 @@ 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.
: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'),
...your model could have a :meth:`~django.db.models.Model.get_absolute_url()`
...your model could have a :meth:`~django.db.models.Model.get_absolute_url`
method that looked like this::
from django.db import models

View File

@ -262,11 +262,11 @@ Taking care in ``get_absolute_url()``
URLs can only contain ASCII characters. If you're constructing a URL from
pieces of data that might be non-ASCII, be careful to encode the results in a
way that is suitable for a URL. The ``django.db.models.permalink()`` decorator
handles this for you automatically.
way that is suitable for a URL. The :func:`~django.core.urlresolvers.reverse`
function handles this for you automatically.
If you're constructing a URL manually (i.e., *not* using the ``permalink()``
decorator), you'll need to take care of the encoding yourself. In this case,
If you're constructing a URL manually (i.e., *not* using the ``reverse()``
function), you'll need to take care of the encoding yourself. In this case,
use the ``iri_to_uri()`` and ``urlquote()`` functions that were documented
above_. For example::

View File

@ -178,25 +178,17 @@ whether a view would raise a ``Http404`` error before redirecting to it::
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.
get_script_prefix()
-------------------
.. function:: get_script_prefix()
Normally, you should always use :func:`~django.core.urlresolvers.reverse` or
:func:`~django.db.models.permalink` to define URLs within your application.
However, if your application constructs part of the URL hierarchy itself, you
may occasionally need to generate URLs. In that case, you need to be able to
find the base URL of the Django project within its Web server
(normally, :func:`~django.core.urlresolvers.reverse` takes care of this for
you). In that case, you can call ``get_script_prefix()``, which will return the
script prefix portion of the URL for your Django project. If your Django
project is at the root of its Web server, this is always ``"/"``.
Normally, you should always use :func:`~django.core.urlresolvers.reverse` to
define URLs within your application. However, if your application constructs
part of the URL hierarchy itself, you may occasionally need to generate URLs.
In that case, you need to be able to find the base URL of the Django project
within its Web server (normally, :func:`~django.core.urlresolvers.reverse`
takes care of this for you). In that case, you can call
``get_script_prefix()``, which will return the script prefix portion of the URL
for your Django project. If your Django project is at the root of its web
server, this is always ``"/"``.

View File

@ -552,12 +552,11 @@ layers where URLs are needed:
* In templates: Using the :ttag:`url` template tag.
* In Python code: Using the :func:`django.core.urlresolvers.reverse()`
* 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.
The :meth:`~django.db.models.Model.get_absolute_url` method.
Examples
--------
@ -622,10 +621,10 @@ view::
)
This is completely valid, but it leads to problems when you try to do reverse
URL matching (through the :func:`~django.db.models.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* URL patterns point at that view.
URL matching (through the :func:`~django.core.urlresolvers.reverse` function
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* URL patterns 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
@ -724,7 +723,7 @@ the fully qualified name into parts, and then tries the following lookup:
render a template.
The current application can also be specified manually as an argument
to the :func:`django.core.urlresolvers.reverse()` function.
to the :func:`django.core.urlresolvers.reverse` function.
3. If there is no current application. Django looks for a default
application instance. The default application instance is the instance

View File

@ -1,3 +1,4 @@
from django.core.urlresolvers import reverse
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@ -14,9 +15,8 @@ class Artist(models.Model):
def __str__(self):
return self.name
@models.permalink
def get_absolute_url(self):
return ('artist_detail', (), {'pk': self.id})
return reverse('artist_detail', kwargs={'pk': self.id})
@python_2_unicode_compatible
class Author(models.Model):