2010-09-13 5 views
0

Мне трудно денормализовать поле в модели django. У меня есть:Denormalising field in 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 ответов изначально связаны с ответом «Продовольствие», и я редактирую его, поэтому он становится связанным с набором ответов «Цвета», как я могу пересчитать количество ответов в наборе ответов с помощью «Продовольствия»? Кажется, что все сигналы посылают новые данные, поэтому я не могу просто переопределить метод сохранения.

Я пробовал использовать сигнал 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