segnale post_save sul campo m2m
-
04-07-2019 - |
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?
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