DRF多对多关系序列化报错:Producto对象无producto属性
Django REST Framework 订单序列化错误修复
问题现象
插入DetallePedido记录后出现序列化错误:
Got AttributeError when attempting to get a value for field
productoon serializerDetallesPedidoSerializer.
The serializer field might be named incorrectly and not match any attribute or key on theProductoinstance.
Original exception text was: 'Producto' object has no attribute 'producto'.
核心原因
Pedido模型的detalles_pedido是多对多关联到Producto,而非DetallePedido实例;PedidoSerializer错误地将模型自带的detalles_pedido字段用DetallesPedidoSerializer序列化,导致DRF把Producto实例传入需要DetallePedido实例的序列化器,自然找不到producto属性;- 虽
create方法成功插入DetallePedido记录,但序列化时读取的是Pedido关联的Producto集合,而非DetallePedido集合。
修复方案
步骤1:修改序列化器字段映射
在PedidoSerializer中,避免使用模型已有的detalles_pedido字段名,改用DetallePedido的反向关联作为数据源:
# serializers.py class PedidoSerializer(serializers.ModelSerializer): # 用新字段名"detalles",指定数据源为Pedido的DetallePedido反向关联集合 detalles = DetallesPedidoSerializer(many=True, source='detallepedido_set') class Meta: model = Pedido # 替换原字段为新的"detalles" fields = ['cliente', 'direccion', 'estado', 'detalles'] extra_kwargs = { 'cliente': {'required': False} } def create(self, validated_data): # 对应修改弹出的字段名为"detalles" productos_data = validated_data.pop('detalles') pedido = Pedido.objects.create(**validated_data) for producto_data in productos_data: DetallePedido.objects.create( pedido=pedido, producto=producto_data['producto'], cantidad=producto_data['cantidad'] ) return pedido
步骤2(可选):优化反向关联命名(更直观)
如果觉得detallepedido_set不够清晰,可在DetallePedido模型中给pedido字段设置related_name:
# models.py class DetallePedido(models.Model): # 添加related_name,让Pedido可以通过pedido.detalles直接访问关联的DetallePedido pedido = models.ForeignKey(Pedido, on_delete=models.CASCADE, related_name='detalles') producto = models.ForeignKey(Producto, on_delete=models.CASCADE) cantidad = models.PositiveIntegerField() def __str__(self): return f'{self.producto.id} - {self.cantidad} - {self.pedido.cliente}'
此时序列化器中的source可改为更简洁的detalles:
detalles = DetallesPedidoSerializer(many=True, source='detalles')
步骤3:调整请求数据字段名
前端请求时,需把原detalles_pedido字段名改为detalles,示例请求体:
{ "direccion": "测试地址", "estado": "pendiente", "detalles": [ {"producto": 1, "cantidad": 2}, {"producto": 3, "cantidad": 1} ] }
修复原理
- 序列化器不再读取
Pedido关联的Producto集合,而是直接读取关联的DetallePedido实例集合; DetallesPedidoSerializer接收正确的DetallePedido对象,能正常获取producto和cantidad字段;- 保留
create方法逻辑,确保DetallePedido记录正确插入数据库。
内容的提问来源于stack exchange,提问作者user26392447
相关产品推荐
相关产品推荐

