Ошибка DRF при сериализации отношения "многие ко многим
Ошибка возникает после вставки записи DetallePedido, сериализатор ищет поля 'producto' и 'cantidad'. А он получает объект Producto и целое число (cantidad) и ищет поле 'producto' внутри объекта Producto, поэтому и возникает ошибка. А в конце функции create() она отправляет объект Pedido с пустым атрибутом detalles_pedido, в котором и должны храниться записи DetallePedido. Есть идеи, как это исправить?
error: Получена ошибка AttributeError при попытке получить значение для поля producto
на сериализаторе DetallesPedidoSerializer
.
Поле сериализатора может быть названо неверно и не соответствовать какому-либо атрибуту или ключу экземпляра Producto
.
Оригинальный текст исключения был: 'Producto' object has no attribute 'producto'.
models.py
class Producto(models.Model):
nombre = models.CharField(max_length=100, blank=False, default='')
precio = models.DecimalField(max_digits=6, decimal_places=2)
coste_envio = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return self.nombre
class Pedido(models.Model):
ESTADOS = {
'pendiente': 'Pendiente',
'pagado': 'Pagado',
'enviado': 'Enviado',
'entregado': 'Entregado',
}
cliente = models.ForeignKey(User, on_delete=models.CASCADE)
direccion = models.CharField(max_length=300)
fecha_creacion = models.DateTimeField(auto_now_add=True)
estado = models.CharField(max_length=10, choices=ESTADOS, default=ESTADOS['pendiente'])
detalles_pedido = models.ManyToManyField(Producto, through='DetallePedido')
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
def __str__(self):
return f'Pedido {self.id} - {self.cliente}'
class DetallePedido(models.Model):
pedido = models.ForeignKey(Pedido, on_delete=models.CASCADE)
producto = models.ForeignKey(Producto, on_delete=models.CASCADE)
cantidad = models.PositiveIntegerField()
def __str__(self):
return f'{self.producto.id} - {self.cantidad} - {self.pedido.cliente}'`
serializers.py
class ProductoSerializer(serializers.ModelSerializer):
class Meta:
model = Producto
fields = ['id', 'nombre', 'precio', 'coste_envio']
class DetallesPedidoSerializer(serializers.ModelSerializer):
producto = serializers.PrimaryKeyRelatedField(queryset=Producto.objects.all())
class Meta:
model = DetallePedido
fields = ['producto', 'cantidad']
class PedidoSerializer(serializers.ModelSerializer):
detalles_pedido = DetallesPedidoSerializer(many=True)
class Meta:
model = Pedido
fields = ['cliente', 'direccion', 'estado', 'detalles_pedido']
extra_kwargs = {
'cliente': {'required': False}
}
def create(self, validated_data):
productos_data = validated_data.pop('detalles_pedido')
pedido = Pedido.objects.create(**validated_data)
for producto_data in productos_data:
detalle = DetallePedido.objects.create(pedido=pedido,
producto=producto_data['producto'],
cantidad=producto_data['cantidad']
)
# Here i can print detalle object and is inserted in db
return pedido
views.py
@api_view(['POST'])
@permission_classes([IsAuthenticated,])
def pedido_create(request):
if request.method == 'POST':
data = request.data.copy()
data['cliente'] = request.user.id
serializer = serializers.PedidoSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
error: Получена ошибка AttributeError при попытке получить значение для поля producto
на сериализаторе DetallesPedidoSerializer
.
Поле сериализатора может быть названо неверно и не соответствовать какому-либо атрибуту или ключу экземпляра Producto
.
Оригинальный текст исключения был: 'Producto' object has no attribute 'producto'.
Вы можете указать источник следующим образом:
class PedidoSerializer(serializers.ModelSerializer):
detalles_pedido = DetallesPedidoSerializer(
many=True, source='detallespedido_set'
)
# …
По умолчанию это related_name
запроса в обратном направлении.