Django post_save 信号就像 pre_save

Django post_save signal acts like pre_save

我正在尝试创建一个简单的信号,为模型创建一个标识符。

class Scheduler(models.Model):
    weekhours = models.ManyToManyField('WeekHour', related_name='schedulers')
    identificator = models.TextField(null=True,blank=True)

class WeekHour(models.Model):
    hour = models.PositiveSmallIntegerField(verbose_name='Hour in week (0 - 7*24')

每次保存 Scheduler 对象时,我想创建或更新 identificator 加入 [weekhour_obj.hour for weekhour_obj in scheduler.weekhours.all()]

的列表

所以我创建了一个 post_save 信号。问题是当我保存 Scheduler 时,信号就像 pre_save 一样。为调度程序设置的 workhours 是旧的,未更新。当我第二次保存它时它起作用了。

@receiver(post_save,sender=models.Scheduler)
def set_identificator(sender,created,instance,**kwargs):
    identificator = ','.join([str(x.hour) for x in instance.weekhours.all().order_by('hour')])
    models.Scheduler.objects.filter(pk=instance.pk).update(identificator = identificator)

你知道问题出在哪里吗?

编辑 - 示例:

当我把 print instance.weekhours.all() 放在信号方法的第一行时,它的行为是这样的:

  1. 在 Django admin 中创建了一个调度程序对象,工作时间为第 2 小时和第 4 小时。 它什么也没打印。
  2. 在管理员中打开调度程序并将 WeekHours 从 2 和 4 更改为 5。 它打印了 <QuerySet [<WeekHour: 2>,<WeekHour: 4>]>
  3. 再次打开调度程序并将工作时间更改为 6 和 7。 它打印了 <QuerySet [<WeekHour: 5>]>

但这是一个 post_save 信号,所以为什么它的行为就像 pre_save

Many-to-many 关系需要先保存父对象,在保存之前不能将项目与 Scheduler 实例相关联。

在您的示例中,您试图在 post_save 中获得 instance.weekhours.all(),但在第一个 save 中它总是 return None。为此,您需要再次保存以获取值。

您可以使用 m2m_changed 而不是 post_save 来创建标识符