From 42fa51c0027b1c40b897a0d51051a63962f95637 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 20 Nov 2012 07:15:16 -0500 Subject: [PATCH] [1.5.X] Fixed #18974 - Warned against using models.permalink Thanks dstufft for the draft patch. Backport of 0e3690d230 from master --- docs/ref/models/instances.txt | 30 +++++++++++++------ docs/ref/unicode.txt | 8 ++--- docs/ref/urlresolvers.txt | 26 ++++++---------- docs/topics/http/urls.txt | 15 +++++----- tests/regressiontests/generic_views/models.py | 4 +-- 5 files changed, 43 insertions(+), 40 deletions(-) diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 1d0ac08061..9f2e007268 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -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 `, -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 diff --git a/docs/ref/unicode.txt b/docs/ref/unicode.txt index ffab647379..784ff33398 100644 --- a/docs/ref/unicode.txt +++ b/docs/ref/unicode.txt @@ -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:: diff --git a/docs/ref/urlresolvers.txt b/docs/ref/urlresolvers.txt index 1bb33c7ca1..528f172061 100644 --- a/docs/ref/urlresolvers.txt +++ b/docs/ref/urlresolvers.txt @@ -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 ``"/"``. diff --git a/docs/topics/http/urls.txt b/docs/topics/http/urls.txt index e178df2af2..00c07da6ea 100644 --- a/docs/topics/http/urls.txt +++ b/docs/topics/http/urls.txt @@ -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 diff --git a/tests/regressiontests/generic_views/models.py b/tests/regressiontests/generic_views/models.py index f59389ef78..30c73d67ca 100644 --- a/tests/regressiontests/generic_views/models.py +++ b/tests/regressiontests/generic_views/models.py @@ -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):