Django es el entorno de desarrollo web para perfeccionistas con límites de tiempo

Trabajar con slugs en URLs

Una de las cosas que los buscadores tienen en cuenta para establecer la relevancia de sus resultados son las palabras que aparecen en las URLs. Por eso conviene que las URLs de nuestros objetos incluyan un slug que los represente.

Un slug es una cadena sin caracteres especiales, en minúsculas y con guiones en lugar de espacios, óptima para ser utilizada en URLs. Con un slug podríamos hacer que una URL tipo /negocios/33/ sea /negocios/mi-negocio/. En este caso el slug sería mi-negocio.

Django tiene un campo SlugField que podemos usar en nuestros modelos precisamente para eso. Si tenemos un campo slug que es único la siguiente URL nos sirve como URL del objeto:

url(r'^negocio/(?P<slug>[-\w]+)/$', mi_vista, name='mi_vista')

Si el slug no es único podemos utilizar la combinación de id y slug. Conviene que el slug aparezca primero ya que los buscadores dan más relevancia a las palabras que aparecen antes en la propia URL:

url(r'^negocio/(?P<slug>[-\w]+)/(?P<id>\d+)/$', mi_vista, name='mi_vista')

Si el slug tiene que generarse dinámicamente de forma transparente para el usuario podemos hacerlo en el método save() del modelo. Podemos utilizar el filtro slugify de django...

from django.db import models
from django.template import defaultfilters

class Negocio(models.Model):
    nombre = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100)

    def save(self, *args, **kwargs):
        self.slug = defaultfilters.slugify(self.nombre)
        super(Negocio, self).save(*args, **kwargs)

...o bien slughifi que es más cuidadoso al generar slugs transformando caracteres acentuados en sus respectivos caracteres sin acentos.

from slughifi import slughifi
# ...
def save(self, *args, **kwargs):
    self.slug = slughifi(self.nombre)
    super(Negocio, self).save(*args, **kwargs)

Generar el slug dinámicamente de forma transparente para el usuario tiene un problema: El slug puede variar y por lo tanto la URL puede cambiar. Podemos aplicar dos soluciones:

  1. Generar el slug sólo la primera vez que se guarda el objeto:

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slughifi(self.nombre)
        super(Negocio, self).save(*args, **kwargs)
    

    La ventaja es que el slug se mantendrá aunque el nombre cambie. La desventaja que el nombre y el slug pueden acabar teniendo poco que ver el uno con el otro.

  2. Regenerar el slug cada vez que se actualice el objeto pero ofrecer la posibilidad de que las URLs antiguas sigan funcionando. Podemos conseguirlo haciendo lo siguiente en nuestra vista:

    from django.http import HttpResponsePermanentRedirect
    from django.shortcuts import get_object_or_404
    
    def mi_vista(request, slug, id):
        try:
            negocio = Negocio.objects.get(slug=slug, id=id)
        except ObjectDoesNotExist:
            negocio = get_object_or_404(Negocio, id=id)
            return HttpResponsePermanentRedirect(negocio.get_absolute_url())
        # ...
    

    De esta forma el slug podrá cambiar si hace falta y para cualquier enlace que exista hacia la URL antigua se devolverá una redirección permanente a la nueva URL.

Publicado por Antonio Melé el Domingo 29 de Agosto de 2010 Compártelo: Facebook: Twitter: | Categorías: trucos, urls

Entradas similares

Subdominios con Django

En ocasiones nos interesa trabajar con subdominios en nuestros proyectos Django. Para ello podemos utilizar un sencillo middleware para subdominios que podemos encontrar en ...


Idiomas en nuestras URLs gracias a django-localeurl

django-localeurl es una aplicación que permite el uso de códigos de idiomas en las URLs de nuestro proyecto. Esto trae la ventaja de que ...


 
Métodos para crear perfiles de usuario

En múltiples ocasiones nos gustaría extender el modelo User para que incluyera otros campos y funciones. La manera "oficial" de hacer esto (la mostrada ...


Descubriendo objetos similares por sus etiquetas 2

Ya hablamos anteriormente sobre cómo descubrir objetos similares por sus etiquetas con la versión 1.0 de Django. Sin embargo la versión de desarrollo ...


 
 

1 comentario:

El Lunes 20 de Diciembre de 2010 Noe Misael Nieto Arroyo dijo:
Muy bien explicado. El poner el id en el url además del slug resolvería el problema de slugs duplicados. Gracias por el aporte.

Escribe un comentario: