django可写嵌套序列化程序和django多态

wvt8vs2t  于 2021-07-14  发布在  Java
关注(0)|答案(0)|浏览(177)

假设我有以下模型:

class DataQuery(models.Model):
  name = models.CharField(...)

class Entity(PolymorphicModel):
  class TargetType(models.IntegerChoices):
    Human  = 1,    _('Human')
    Animal = 2,    _('Animal')

  targetType = models.PositiveSmallIntegerField(choices=TargetType.choices, null=False)
  dataQuery = models.OneToOneField(DataQuery, on_delete=models.CASCADE, null=True, related_name="targetEntity")

class HumanEntity(Entity):
  name = models.CharField(...)

  def save(self, *args,**kwargs):
    self.targetType = Entity.TargetType.Human
    return super().save(*args,**kwargs)

class AnimalEntity(Entity):
  numPaws= models.PositiveSmallIntegerField(...)

  def save(self, *args,**kwargs):
    self.targetType = Entity.TargetType.Animal
    return super().save(*args,**kwargs)

使用以下序列化程序:

class HumanSerializer(serializers.ModelSerializer):
    name = serializers.TextField(...)
    class Meta:
        model = HumanEntity
        fields = ('name', )

class AnimalSerializer(serializers.ModelSerializer):
    numPaws = serializers.IntegerField(...)
    class Meta:
        model = AnimalSerializer
        fields = ('numPaws', )

class EntityPolymorphicSerializer(WritableNestedModelSerializer, PolymorphicSerializer):
    model_serializer_mapping = {
        HumanEntity: HumanSerializer,
        AnimalEntity: AnimalSerializer,
    }

    class Meta:
        model = Entity
        fields = '__all__'

class DataQuerySerializer(WritableNestedModelSerializer):
    id = serializers.ReadOnlyField()
    name = serializers.CharField(),
    targetEntity = EntityPolymorphicSerializer()

    class Meta:
        model = DataQuery
        fields = ('id', 'name', 'targetEntity' )

我有个模特 DataQuery 具有1:1Map的 AnimalEntity 或者 HumanEntity 模型。如果我序列化 DataQuery 用一个 HumanEntity ,我得到以下(正确)输出:

{
  id : 1
  name : "testQuery"
  targetEntity : {
   resourcetype : "HumanEntity",
   name : "John Doe"
  }  
}

POST 对我的端点的调用也起作用 DataQuery 以及潜在的 HumanEntity 创建时没有任何问题。
我不包括 id 在内部 Entity 序列化程序,因为这与此api的使用者无关。对于他们来说,只需要知道查询可以容纳动物或人类。
现在我想更新我的 DataQuery 示例并更改基础 HumanEntity 到一个 AnimalEntity . 因此,我 PUT 以下内容:

{
  id : 1
  name : "testQuery"
  targetEntity : {
   resourcetype : "AnimalEntity",
   numPaws : 4
  }  
}

现在,奇怪的事情发生了。没有什么。不 AnimalEntity 已创建,并且 HumanEntity 也没有改变(如果我改变 HumanEntity 通过输入不同的名称,可以正确更改名称)。似乎可写的 DataQuerySerializer 不太明白底层示例应该被切换出去(即删除旧示例,创建新示例)。
我在这里浏览了相关代码。因为我不想包括 pk 在嵌套模型序列化程序中,现有的 pkHumanEntity 已检索。不知何故(我想这是由于 PolymorphicSerializer )这是在正确的序列化程序中完成的 AnimalEntitySerializer . 但是由于传递的字段与基础模型不兼容,所以什么也不会发生。
如果我把 OneToOneFieldDataQuery 就像这样:

class DataQuery(models.Model):
  ...
 targetEntity = models.OneToOneField(Entity, on_delete=models.CASCADE, null=True)

有点用,但不是真的。每次我做一个更新(即使没有任何改变),一个新的 HumanEntity 或者 AnimalEntity 已创建。但是序列化程序尊重 PUT 并创建正确的模型(不过,旧版本不会被删除)
我期望什么?当做一个 PUT ,我想更新现有示例,或者,如果我决定切换实体的类型,则创建正确的示例并删除另一个示例。我不确定 on_delete=CASCADE 是任何帮助(无论哪一方),因为我真正需要的是一个领域,说 If the related field is null, delete myself .
我非常清楚,我可以(可能相当容易)通过重写 update 方法 DataQuerySerializer ,但那样我就不需要 WriteableNestedSerializer 首先。
也许有什么我忽略了,任何帮助都将不胜感激。

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题