0

我有两个模型:ExamQuestion。每个问题都有在每次考试中自动计算的分数。

所以这是我的文件:

#Models.py
class Exam(models.Model):
    questions = models.ManyToManyField(Question)
    title = models.CharField()
class Question(models.Model):
    title = models.CharField()
    answer = models.TextField()
    points = models.PositiveSmallIntegerField()

#Forms.py
class ExamForm(ModelForm):
    class Meta:
        model = Exam
        fields = '__all__'

#Views.py
if form.is_valid():
    new_exam = form.save(commit=False)
    # Some modify goes here. 
    new_exam.save()
    form.save_m2m()
    return redirect('view_exam')

我确实为此定制了模型save()方法:Exam

 def save(self, *args, **kwargs):
        self.point = 0
        for question in self.questions:
                self.point += question.point
        super(Exam, self).save(*args, **kwargs)

但我得到了这个错误:

"<Exam: NewObject>" needs to have a value for field "id" before this many-to-many relationship can be used.

我怎样才能做到这一点而不会引发任何错误?

我的目标:对于每一个新创建的考试,计算这个考试的问题点并将它们放入模型points领域Exam

4

1 回答 1

2

将可以从数据库中的其他字段/表计算出来的东西保存到模型中从来都不是一个好主意,尤其是在这取决于其他模型的情况下。例如,当您在某个阶段创建新值时,太容易忘记更新值Question。你只会在你的数据库中得到不一致。

删除您的自定义save()方法,因为它不执行任何操作。

如果您想知道总点数,请添加一个自定义 getterExam来即时计算:

#At the first of models.py -> from django.db.models import Sum 
@property
def points(self):
    if self.pk:
       return self.questions.all().aggregate(Sum('points'))['points__sum']
    else:
       return 0

或者用你的总结:

@property
def points(self):
    if self.pk:
        point = 0
        questions = self.questions.all()
        for question in questions :
            point += question.point
        return point
    else:
        return 0

使用此属性,您可以exam.points在代码中的任何位置执行此操作,并且它将是最新的。

于 2019-08-08T12:28:02.563 回答