Pregunta

Tengo un modelo de artículo bastante genérico, con relación m2m al modelo de etiqueta. Quiero seguir contando el uso de cada etiqueta, creo que la mejor manera sería desnormalizar el campo de recuento en el modelo de etiqueta y actualizarlo cada vez que se guarde el artículo. ¿Cómo puedo lograr esto, o tal vez hay una mejor manera?

¿Fue útil?

Solución

Puede hacer esto creando un modelo intermedio para la relación M2M y utilícelo como gancho para las señales post_save y post_delete para actualizar la columna desnormalizada en el Tabla Article .

Por ejemplo, hago esto para los recuentos favoritos de Question en soclone , donde User s tiene una relación M2M con Question s:

from django.contrib.auth.models import User
from django.db import connection, models, transaction
from django.db.models.signals import post_delete, post_save

class Question(models.Model):
    # ...
    favourite_count = models.PositiveIntegerField(default=0)

class FavouriteQuestion(models.Model):
    question = models.ForeignKey(Question)
    user     = models.ForeignKey(User)

def update_question_favourite_count(instance, **kwargs):
    """
    Updates the favourite count for the Question related to the given
    FavouriteQuestion.
    """
    if kwargs.get('raw', False):
        return
    cursor = connection.cursor()
    cursor.execute(
        'UPDATE soclone_question SET favourite_count = ('
            'SELECT COUNT(*) from soclone_favouritequestion '
            'WHERE soclone_favouritequestion.question_id = soclone_question.id'
        ') '
        'WHERE id = %s', [instance.question_id])
    transaction.commit_unless_managed()

post_save.connect(update_question_favourite_count, sender=FavouriteQuestion)
post_delete.connect(update_question_favourite_count, sender=FavouriteQuestion)

# Very, very naughty
User.add_to_class('favourite_questions',
                  models.ManyToManyField(Question, through=FavouriteQuestion,
                                         related_name='favourited_by'))

Se ha discutido un poco en la lista de correo de django-developers sobre la implementación de un medio de declaración declarativa de desnormalizaciones para evitar tener que escribir código como el anterior:

Otros consejos

Esta es una nueva característica en Django 1.2: http://docs.djangoproject.com/en/dev/ref / señales / # m2m-cambiado

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top