post 仅在调用更新时保存信号

post save signal only when update called

你好,我有两个模型和一个 post_save 信号,但我的信号只有在更新对象时有效,而在我创建新对象时它不起作用

我的代码:

class Attendance(models.Model):
    classroom = models.ForeignKey('Class', on_delete=models.CASCADE)
    student = models.ForeignKey(User, on_delete=models.CASCADE)
    is_present = models.BooleanField(default=False)
    present_time = models.DateTimeField(null=True, blank=True)

    def __str__(self):
        return self.student.username


class Class(models.Model):
    course = models.ForeignKey(Course, on_delete=models.CASCADE)
    students = models.ManyToManyField(User)
    quantity = models.PositiveSmallIntegerField()
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

    class Meta:
        unique_together = ['quantity', 'course']


    def __str__(self):
        return f'{self.quantity} / {self.course}'


@receiver(post_save, sender=Class)
def create_attendance(sender, instance, **kwargs):
    for student in instance.students.all():
        try:
            Attendance.objects.get(classroom=instance, student=student)
        except Attendance.DoesNotExist:
            Attendance.objects.create(classroom=instance, student=student)

在您 创建 实例的那一刻, instance.students 尚未 填充(尚未),因此 empty,这意味着 for student in instance.students.all() 将枚举空集合,因此根本不会枚举 .

这是因为它首先需要创建一个带有主键的记录,然后将其用于 junction table,这是(许多) 使用信号通常 不是 一个好主意的原因。

使用 m2m_changed signal [Django-doc] 可能会更好,因此可以这样实现:

@receiver(m2m_changed, sender=Class.students.through)
def create_attendance(sender, instance, action, pk_set=None, **kwargs):
    if action == 'post_add':
        for <b>pk in pk_set</b>:
            Attendance.objects.get_or_create(classroom=instance, <b>student_id=pk</b>) 

但是造型看起来有点奇怪。为什么不让 Attendance 成为你 ManyToManyFieldthrough model [Django-doc]?这样 Django 将创建 Attendance 记录,然后您可以相应地更新这些记录。

post_save 信号中有一个 created 参数,当创建实例时为 True,当创建实例时为 False未创建(更新)。

@receiver(post_save, sender=Class)
def create_attendance(sender, instance, created, **kwargs):
    if not created:  
        for student in instance.students.all():
            try:
                Attendance.objects.get(classroom=instance, student=student)
            except Attendance.DoesNotExist:
                Attendance.objects.create(classroom=instance, student=student)