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

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 de Django incluye funciones de agregación que nos permiten realizar este tipo de tareas de una manera más cómoda sin tener que utilizar SQL puro como hacíamos antes.

Partiremos exactamente del mismo código que usamos la vez anterior: Dos modelos definidos en el archivo models.py de nuestra aplicación:

class Etiqueta(models.Model):
    nombre = models.CharField(max_length=40)
    slug = models.SlugField(max_length=40)

class Entrada(models.Model):
    titulo = models.CharField(max_length=150)
    slug = models.SlugField(max_length=150, unique=True)
    cuerpo = models.TextField()
    etiquetas = models.ManyToManyField(Etiqueta, related_name="entradas")

Queremos construir una vista que reciba el slug perteneciente a una entrada y obtenga dicha entrada y sus entradas similares en función de las etiquetas que tienen las distintas entradas.

Para ello utilizamos la función de agregación Count que se encuentra en django.db.models y que nos va a permitir realizar una consulta SQL con COUNT de una forma sencilla. Primero realizamos el import correspondiente:

from django.db.models import Count

A continuación creamos la estructura básica de nuestra vista que recibe un slug y selecciona la entrada correspondiente al mismo:

from django.db.models import Count
from django.shortcuts import get_object_or_404

def ver_entrada(request,slug):
    entrada = get_object_or_404(Entrada, slug=slug)

Necesitamos la lista de entradas que comparten etiquetas con esta entrada. Para ello obtenemos en una lista cada id de las etiquetas correspondientes a la entrada utilizando el método values_list. Esta lista nos servirá para encontrar otras entradas que compartan dichas etiquetas:

entrada_etiquetas_ids = entrada.etiquetas.values_list('id', flat=True)

Tras esto sólo queda seleccionar entradas públicas cuyas etiquetas figuren en dicha lista, contabilizar el número de etiquetas en común con nuestra entrada original y ordernar las entradas resultantes por número de entradas en común, de mayor a menor similitud con la entrada original.

similares = Entrada.objects.filter(publico=True, etiquetas__in=entrada_etiquetas_ids).exclude(id=entrada.id).annotate(mismas_etiquetas=Count('etiquetas')).order_by('-mismas_etiquetas')

Con todo esto el código de nuestra vista quedaría de la siguiente manera:

from django.db.models import Count
from django.shortcuts import get_object_or_404

def ver_entrada(request,slug):
    entrada = get_object_or_404(Entrada, slug=slug)
    entrada_etiquetas_ids = entrada.etiquetas.values_list('id', flat=True)
    similares = Entrada.objects.filter(publico=True, etiquetas__in=entrada_etiquetas_ids).exclude(id=entrada.id).annotate(mismas_etiquetas=Count('etiquetas')).order_by('-mismas_etiquetas')
    # ...

Si comparamos este código con el que teníamos que utilizar antes de la introducción de las funciones de agregación vemos cómo éstas nos han simplificado enormemente el trabajo. ¡Gracias otra vez, Django!

Publicado por Antonio Melé el Martes 24 de Febrero de 2009 Compártelo: Facebook: Twitter: | Categorías: etiquetas, trucos

Entradas similares

Descubriendo objetos similares por sus etiquetas

Si estás utilizando la versión de desarrollo de Django es mejor que utilices las funciones de agregación.

Muchas veces utilizamos etiquetas para nuestros modelos ...


Settings accesibles desde las plantillas

Muchas veces deseamos acceder a los settings de nuestro proyecto desde alguna de nuestras plantillas. Lo ideal es crear un context processor que nos ...


 
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 ...


Modificar la QuerySet de un ModelChoiceField dinámicamente

El campo de formulario ModelChoiceField sirve para permitir la selección de un elemento entre los objetos resultantes de una QuerySet. La QuerySet inicial puede ...


 
 

0 comentarios:

No hay ningún comentario todavía.

Escribe un comentario: