Django: get_absolute_url y permalink

written by uve 6 September 2010

Estoy aprovechando hoy para retomar la aplicación de noticias que estoy utilizando en MenudoProblema para sacar una nueva versión e introducir algunas mejoras. La primera de ellas: get_absolute_url.

get_absolute_url es un método de los modelos, que define como se calcula la URL para un objeto dado. Yo en concreto estoy trabajando sobre el modelo Entry, que representa una noticia:

class Entry(models.Model):
   title = models.CharField(...)
   ...

   def get_absolute_url(self):
      return '/noticias/%s/' % self.pk

Pero, ¿de qué nos sirve esto? Este método se utiliza en la interfaz de administración. Si el objeto define este método, cuando se edite aparecerá una opción "Ver en el sitio", que nos enlazará directamente a la URL.

Además, este método es utilizado en otros componentes de Django, como en el framework de sindicación. Así que es recomendable implementarlo.

Pero, ¿qué problema aparece? Si ahora decidimos cambiar la url donde están las noticias, por ejemplo a /blog/noticias/ en lugar de /noticias/, necesitaremos modificar el código para que todo siga funcionando.

Solución: el decorador permalink. Este decorador nos permite desacoplar los modelos de URLconf. Simplemente devolvemos la vista y los parámetros que la vista requiere. Por ejemplo, si tenemos esta entrada en urlpatterns:

(r'^noticias/(\d+)/$', 'menudoproblema.noticias.views.entry_view'),

podemos realizar lo siguiente:

from django.db import models

class Entry(models.Model):
   ...
   @models.permalink
   def get_absolute_url(self):
      return ('menudoproblema.noticias.views.entry_view', [str(self.id)])

Aún así, esto nos puede plantear un problema con las vistas genéricas, ya que estas pueden recibir distintos modelos, lo que crea confusión al localizar la URL, ya que coinciden múltiples entradas de urlpatterns.

Esto se puede solucionar utilizando patrones URL con nombres, "named URL patterns":

(r'^noticias/(\d+)/$', 'django.views.generic.list_detail.object_detail', name='entry_view'),

from django.db import models

class Entry(models.Model):
   ...
   @models.permalink
   def get_absolute_url(self):
      return ('entry_view', [str(self.id)])

Tags

La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.