2010-09-13 58 views
0

我发现很难在django模型中规范化字段。我有:django中的非规范化字段

class AnswerSet(models.Model): 
    title = models.CharField(max_length=255) 
    num_answers = models.PositiveIntegerField(editable=False, default=0) 
    answers = models.ManyToManyField(Answer, through='AnswerSetAnswer') 
    ... 

class AnswerSetAnswer(models.Model): 
    answer = models.ForeignKey(Answer) 
    answer_set = models.ForeignKey(AnswerSet) 
    ... 

我希望num_answers包含集合中答案的数量。

如果5个答案最初与AnswerSet“Food”相关联,并且我编辑了一个答案以便它与AnswerSet“Colors”相关联,那么如何重新计算AnswerSet中含有“Food”的答案数?所有的信号似乎只发送新的数据,所以我不能只是重写保存方法。

我试过使用m2m_changed信号,但是当我通过管理窗体编辑关系时,它永远不会被调用。

这里是我的代码吗:

def update_answer_set_num_answers(sender, **kwargs): 
    """ 
    Updates the num_answers field to reflect the number of answers 
    associated with this AnswerSet 
    """ 
    instance = kwargs.get('instance', False) 

    print "no instance"    # never gets here 

    if not instance: 
     return 

    action = kwargs.get('action') 

    print "action: ", action 

    if (action != 'pre_remove' and action != 'pre_add' and action != 'clear'): 
     return 

    reverse = kwargs.get('reverse') 

    if reverse: 
     answer_set = instance.answer_set 
    else: 
     answer_set = instance.answer_set 
    num_answers = AnswerSetAnswer.objects.filter(answer_set=answer_set.id).count() 

    if (action == 'pre_remove'): 
     num_answers -= int(kwargs.get('pk_set')) 
    elif (action == 'pre_add'): 
     num_answers += int(kwargs.get('pk_set')) 
    elif (action == 'clear'): 
     num_answers = 0 

    answer_set.num_answers = num_answers 

    print 'n a: ', answer_set.num_answers 
    answer_set.save() 


m2m_changed.connect(update_answer_set_num_answers, \ 
    AnswerSet.answers.through, weak=False) 

回答

1

你真的需要denormalise呢?你可以用一个简单的聚合来计算它:

from django.db.models import Count 
answersets = AnswerSet.objects.all().annotate(num_answers=Count('answers') 
+0

是的,它会很方便。例如,我想要显示5个随机答案集,它们都有3个答案。我希望有很多答案集,这将有助于扩大规模 – Roger 2010-09-13 20:47:12