我有这个信号,我希望它不要运行,一旦它已经检查了每个示例一次,目前它福尔斯陷入一个无限递归循环,因为它触发自己每次运行。
from django.db.models.signals import (
post_save,
)
from django.dispatch import receiver
from app.models import (
QuestionForm,
Question,
)
@receiver(post_save, sender=form)
def get_max_score(
sender: form,
instance: form,
**kwargs: dict,
) -> None:
forms = form.objects.all()
for form in forms.iterator():
total = 0
questions = form.questions.all()
for item in questions.iterator():
total += item.points
form.set_score(total)
form.save()
字符串
感谢任何帮助,如果答案比n^2简单,就可以加分。
编辑:这是表单模型本身:
class QuestionForm(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
questions = models.ManyToManyField(
Question,
related_name='questions'
)
created_at = models.DateTimeField(
auto_now_add=True,
editable=False,
)
updated_at = models.DateTimeField(
auto_now=True,
editable=False,
)
max_score = models.IntegerField(
default=0,
)
def __str__(self):
return self.name
def get_score(self):
return self.max_score
def set_score(self, score):
self.max_score = score
型
1条答案
按热度按时间aij0ehis1#
我强烈建议 * 不要 * 将分数存储在
form
对象中。事实上,这不仅可以避免信号的问题:我们可以在数据库端更有效地这样做,并且只有当我们 * 需要 * 分数时,也使它更健壮。信号通常是一个坏主意。事实上,信号可以规避,例如使用**
.bulk_create(…)
**[Django-doc]不会为创建的对象触发信号。还有很多情况下数据可以更改:创建记录,更新记录,删除记录。事实证明,即使在同一个数据库中,不容易。我总结了this article [django-antipatterns]中信号的一些问题。因此,最好省略
score
:字符串
现在,如果我们想要
Form
s与相关Question
s的相应得分,我们可以使用:用途:型
由
QuerySet
产生的Form
s将有一个额外的属性.score
,它将包含 relatedQuestion
s的.points
之和。如果查询集被过滤掉,它也不会聚合我们不需要的查询集,因为聚合是由数据库完成的,这通常是非常有效的。备注:**
related_name=…
**参数[Django-doc]是 reverse 中关系的名称,因此在这种情况下从Question
模型到QuestionForm
模型。因此,将其命名为与正向关系相同没有多大意义。因此,您可能需要考虑将questions
关系重命名为forms
。