假设我有以下模型:
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:1 映射。如果我序列化已经用 a 创建的 a ,我会得到以下(正确的)输出:AnimalEntity
HumanEntity
DataQuery
HumanEntity
{
id : 1
name : "testQuery"
targetEntity : {
resourcetype : "HumanEntity",
name : "John Doe"
}
}
POST
对我的端点的调用也有效,DataQuery
并且底层HumanEntity
的创建没有任何问题。
我没有故意id
在内部Entity
序列化程序中包含 an,因为这与此 API 的使用者无关。对他们来说,只需要知道查询可以包含动物或人类。
现在我想更新我的DataQuery
实例并将底层更改HumanEntity
为AnimalEntity
. 因此PUT
,我如下:
{
id : 1
name : "testQuery"
targetEntity : {
resourcetype : "AnimalEntity",
numPaws : 4
}
}
而现在,奇怪的事情发生了。没有什么。否AnimalEntity
已创建,并且HumanEntity
也没有更改(如果我HumanEntity
通过输入不同的名称来更改,则名称将正确更改)。似乎可写嵌套DataQuerySerializer
并没有完全理解应该关闭底层实例(即删除旧的,创建新的)。
我在这里逐步浏览了相关代码。由于我不想pk
在嵌套模型序列化程序中包含 a,因此检索了现有pk
的。HumanEntity
不知何故(我想这是由于PolymorphicSerializer
)这是从正确的序列化程序中完成的,AnimalEntitySerializer
. 但是由于传递的字段与底层模型不兼容,所以什么也没有发生。
OneToOneField
如果我通过将 1:1 映射到DataQuery
类似的位置来反转 1:1 映射:
class DataQuery(models.Model):
...
targetEntity = models.OneToOneField(Entity, on_delete=models.CASCADE, null=True)
它有点工作,但不是真的。每次我进行更新(即使没有更改任何内容),都会创建一个新的HumanEntity
or AnimalEntity
。但是序列化程序尊重 的变化PUT
并创建正确的模型。(不过,旧的并没有被删除)
我期待什么?
执行 a 时PUT
,我想更新现有实例,或者,如果我决定切换实体的类型,则创建正确的实例并删除另一个实例。我不确定是否on_delete=CASCADE
有任何帮助(无论在哪一边),因为我真正需要的是一个显示If the related field is null, delete myself
.
我完全知道我可以(可能很容易)通过覆盖 的update
方法来解决这个问题DataQuerySerializer
,但是我一开始就不需要了WriteableNestedSerializer
。
也许我忽略了一些东西,任何帮助将不胜感激。