2008-10-27 41 views
6

我有一個非常通用的文章模型,與標記模型的m2m關係。我想保留每個標籤用法的計數,我認爲最好的方法是對標籤模型上的計數字段進行非規範化並在每次保存文章時進行更新。我怎樣才能做到這一點,或者有更好的辦法?m2m字段post_save信號

回答

2

您可以通過爲M2M關係創建intermediate model並將其用作post_savepost_delete信號的鉤子來更新Article表中的非規格化列。

例如,我這樣做是爲soclone收藏最多Question計數,其中User■找與Question個M2M關係:

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的開發者郵件有關實現列表中的一點討論聲明聲明denormalisations的一種手段,以避免不必編寫代碼像上面:

+0

有這種技術的疑難雜症是:如果你想在一個表格中使用這些類,form.save_m2m將不再起作用 – Rob 2009-03-20 13:34:49