إشارة post_save على حقل M2M
-
04-07-2019 - |
سؤال
لدي نموذج مقال عام جميل ، مع علاقة M2M بنموذج العلامة. أرغب في الحفاظ على حساب كل استخدام علامة ، وأعتقد أن أفضل طريقة هي حقل العد العدسي على نموذج العلامة وتحديثه في كل مرة يتم فيها حفظ مقالة. كيف يمكنني إنجاز هذا ، أو ربما هناك طريقة أفضل؟
المحلول
يمكنك القيام بذلك عن طريق إنشاء نموذج وسيطة لعلاقة M2M واستخدمها كخطاف الخاص بك ل post_save
و post_delete
إشارات لتحديث العمود dechormised في Article
الطاولة.
على سبيل المثال ، أفعل هذا من أجل Favourited Question
التهم في Soclone, ، أين User
S لها علاقة M2M مع Question
س:
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'))
كان هناك القليل من النقاش حول القائمة البريدية لمطوري Django حول تنفيذ وسيلة لإعلان dechormalisations بشكل معني لتجنب الاضطرار إلى كتابة رمز مثل ما سبق:
نصائح أخرى
هذه ميزة جديدة في Django 1.2:http://docs.djangoproject.com/en/dev/ref/signals/#m2m-changed