2010-09-13 71 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