post_save Signal auf M2M Feld
-
04-07-2019 - |
Frage
Ich habe ein ziemlich generisches Artikelmodell mit M2M -Beziehung zum Tag -Modell. Ich möchte die Anzahl der einzelnen Tag -Verwendung beibehalten. Ich denke, der beste Weg wäre es, das Feld des Zählers auf dem Tag -Modell zu verhindern und jedes Mal zu aktualisieren, wenn Artikel gespeichert werden. Wie kann ich das erreichen oder vielleicht gibt es einen besseren Weg?
Lösung
Sie können dies tun, indem Sie eine erstellen Zwischenmodell Für die M2M -Beziehung und verwenden Sie sie als Ihren Haken für die post_save
und post_delete
signalisiert, um die Denormalisierte Spalte in der zu aktualisieren Article
Tisch.
Zum Beispiel mache ich das für Favorited Question
zählt in Soclone, wo User
s haben eine M2M -Beziehung mit 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'))
Über die Mailingliste von Django-Entwicklern wurde ein wenig über die Implementierung einer Mittel zur deklarativen Deklarierung der Denormalisierung geführt, um nicht so beschrieben zu werden:
Andere Tipps
Dies ist eine neue Funktion in Django 1.2:http://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed