首页 > 解决方案 > Django Rest Framework - PrimaryKeyRelatedField 与 post_save 信号

问题描述

我正在构建一个端点,它使用 PrimaryKeyRelatedField 来设置下面提供的示例 House 模型的 ManyToOne/Reverse Foreign key 关系:

class House(models.Model):
    name = models.CharField(max_length=245)
    

class Car(models.Model):
    name = models.CharField(max_length=245)
    house = models.ForeignKey(House, on_delete=models.DO_NOTHING, null=True, related_name='cars')

序列化程序以下列方式使用 PrimaryKeyRelatedField:

class HouseSerializer(serializers.ModelSerializer):
    cars = serializers.PrimaryKeyRelatedField(queryset=models.Car.objects.all(), many=True)

    class Meta:
        model = models.House
        fields = "__all__"

我想创建一个信号,在保存房屋后,对相关汽车进行处理。我尝试了两种选择:

@receiver(post_save, sender=models.House)
def post_save_house(sender, **kwargs):
    """
    House is saved before its related Car objects so instance.cars.all() is an unupdated queryset
    """
    instance = kwargs['instance']
    print(instance.cars.all())


@receiver(post_save, sender=models.Car)
def post_save_car(sender, **kwargs):
    """
    Car is not saved but updated through queryset.update() so signal does not fire
    """
    instance = kwargs['instance']
    print(instance)

但是,似乎在通过HouseSerializer更新House对象及其相关的Car对象时,instance.cars.all()查询集仍然对应于未更新的查询集。我尝试从数据库中重新获取对象并清除查询集,但这似乎不是问题。似乎PrimarykeyRelatedField在更新相关的Car对象之前首先保存了House对象,考虑到在创建时, House对象在将Car对象附加到它之前必须存在,这是有道理的。此外,汽车对象不发送 post_save 信号(我怀疑 queryset.update() 用于更新外键?)所以在那里收听 post_save 信号也不起作用。

考虑到这一点,如何通过反向访问器创建 post_save 行为来设置外键?

标签: djangodjango-rest-frameworkdjango-signals

解决方案


推荐阅读