Domanda

Ho un modello articolo piuttosto generico, con m2m rispetto al modello Tag. Voglio tenere il conto dell'utilizzo di ogni tag, penso che il modo migliore sarebbe denormalizzare il campo di conteggio sul modello di tag e aggiornarlo ogni volta che viene salvato l'articolo. Come posso farlo, o forse c'è un modo migliore?

È stato utile?

Soluzione

Puoi farlo creando un modello intermedio per la relazione M2M e utilizzalo come hook per i segnali post_save e post_delete per aggiornare la colonna denormalizzata nella Tabella Article .

Ad esempio, lo faccio per i conteggi Domanda preferiti in soclone , dove Utente ha una relazione M2M con Domanda 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'))

C'è stato un po 'di discussione sulla mailing list degli sviluppatori di django sull'implementazione di un mezzo per dichiarare dichiaratamente denormalizzazioni per evitare di dover scrivere codice come sopra:

Altri suggerimenti

Questa è una nuova funzionalità di Django 1.2: http://docs.djangoproject.com/en/dev/ref / segnali / # m2m-cambiato

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top