2008-10-27 40 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