在Django-Rest-Framework中反序列化嵌套对象



大家好,

我正在尝试做一个包含嵌套对象的PUT请求,我无法获得正确更新。在django-rest-framework文档中似乎没有任何明显的帮助,我研究了一些其他类似问题的解决方案,但没有一个有帮助(设置many=false,更改为ModelSerializer,专用序列化器等)。

关于地址的其他内容将正确更新并返回200响应(django日志中也没有错误)。如果我认为django-rest-framework可以免费为我处理这一切,那我错了吗?我是否必须在序列化器中重写更新和创建方法来验证和保存嵌套对象?

我认为这是因为我在地址序列化器中将序列化器设置为read_only。但是,如果我删除序列化器上的read_only修饰符,它会给出关于已经存在的错误:

{
"province": {
"province": [
"valid province with this province already exists."
]
}
}

这是我不期望的行为,也不知道如何解决。我不试图添加或更新。我只是想更改地址中的省号。省字段,我不能使用字符串"MB"因为它需要一个对象。我想要这样的行为:

UPDATE agent_business_address
SET province = 'MB'
WHERE agent_id = 12345;
-- agent_business_address.province has a foreign key constraint on valid_province.province
-- valid_province is populated with all the 2-letter abbreviations for provinces(

我向/api/agent-business-address/发出这个PUT请求

{
"address": "123 Fake St",
"agent_id": 12345,
"city": "Calgary",
"dlc": "2021-10-11 14:03:03",
"operator_id": 4,
"postal_code": "A1B 2C3",
"province": {
"description": "Manitoba",
"province": "MB"
},
"valid_address": "N"
}

这个ViewSet接收到的

class AgentBusinessAddressViewSet(viewsets.ModelViewSet):
queryset = AgentBusinessAddress.objects.all()
serializer_class = AgentBusinessAddressSerializer

有关序列化器:

class AgentBusinessAddressSerializer(serializers.HyperlinkedModelSerializer):
province = ValidProvinceSerializer(read_only=True) # Removing the read_only causes the error above.
class Meta:
model = AgentBusinessAddress
fields = ('agent_id', 'operator_id', 'dlc', 'address', 'city', 'province', 'postal_code', 'valid_address')
class ValidProvinceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ValidProvince
read_only_fields = ('operator_id', 'dlc')
fields = ('province', 'description')

相关模型:

class AgentBusinessAddress(models.Model):
agent = models.OneToOneField(Agent, models.DO_NOTHING, primary_key=True)
operator_id = models.SmallIntegerField()
dlc = models.DateTimeField()
address = models.CharField(max_length=100)
city = models.CharField(max_length=80)
province = models.ForeignKey('ValidProvince', models.DO_NOTHING, db_column='province')
postal_code = models.CharField(max_length=7)
valid_address = models.CharField(max_length=1)
class Meta:
managed = False
db_table = 'agent_business_address'
class ValidProvince(models.Model):
province = models.CharField(primary_key=True, max_length=2)
operator_id = models.SmallIntegerField()
dlc = models.DateTimeField()
description = models.CharField(max_length=30, blank=True, null=True)
class Meta:
managed = False
db_table = 'valid_province'

如有任何帮助,不胜感激。

在重读了几次之后,在专门的序列化器帖子的帮助下解决了这个问题。

我将序列化器更新为:

# This gets called for non-GET requests.
class AgentBusinessAddressSerializer(serializers.ModelSerializer):
class Meta:
model = AgentBusinessAddress
fields = ('__all__')
# This get called for GET requests.
class AgentBusinessAddressReadSerializer(AgentBusinessAddressSerializer):
province = ValidProvinceSerializer(read_only=True)
class Meta:
model = AgentBusinessAddress
fields = ('__all__')

我将视图集更新为:

class AgentBusinessAddressViewSet(viewsets.ModelViewSet):
queryset = AgentBusinessAddress.objects.all()

def get_serializer_class(self):
if self.request.method in ['GET']:
return AgentBusinessAddressReadSerializer
return AgentBusinessAddressSerializer

现在我在PUT请求中发送省份的主键:

{
"address": "123 Fake St",
"agent": 10000003,
"city": "Calgary",
"dlc": "2021-10-11 19:47:38",
"operator_id": 4,
"postal_code": "A1B 2C3",
"province": "NS",
"valid_address": "N"
}

我得到一个PUT 200响应,并在DB中验证省现在是'NS'。

{
"agent": 10000003,
"operator_id": 4,
"dlc": "2021-10-11T19:47:38",
"address": "123 Fake St",
"city": "Calgary",
"postal_code": "A1B 2C3",
"valid_address": "N",
"province": "NS",
}

最新更新