Django创建订单报Product匹配查询不存在错误排查
问题根因
你遇到的Product matching query does not exist报错 + 订单实际创建成功的现象,由两类问题共同导致:
- Postman请求配置错误,导致后端解析请求参数时拿到错误的商品ID,查询商品失败
- 视图代码本身缺少事务保护、存在字段名错误,报错后无法回滚已经创建的订单数据,才会出现“数据落库但接口返回错误”的不一致问题
Postman侧修复步骤
- 打开Postman的请求头配置,确认存在
Content-Type: application/json头,不要留空或者填成form-data相关类型 - 把请求体从form-data/x-www-form-urlencoded标签页移到raw标签页,raw右侧的类型下拉框选择
JSON,不要在Params、form-data里重复传同名参数 - 确认请求体里
orderItems数组下每个对象的product字段值,都是数据库里真实存在的商品主键ID,不要传已删除的商品ID,也不要在数组里留空的多余项(比如数组最后多写一个逗号带空对象)
代码侧必修复问题
仅改Postman配置无法解决数据一致性问题,必须同步修复以下代码bug:
- 添加数据库事务:当前代码先创建订单、收货地址,再循环创建订单项,中间任意一步报错,前面已经写入数据库的数据不会回滚,就会产生脏数据。需要给视图加事务装饰器,出错时全部回滚。
- 修复库存字段名错误:
Product模型里库存字段定义为stock,视图里错误写为countInStock,执行到扣库存逻辑时会直接抛属性错误,需要统一字段名。 - 补全收货地址字段:当前创建
ShippingAddress时只传了address字段,city、postalCode、country都未从请求中取值,会导致收货地址数据缺失。 - 添加商品不存在的异常捕获:查询商品时如果ID不存在,直接返回明确的400错误,不要抛出框架默认的500异常。
修复后的视图代码示例
from django.db import transaction from rest_framework import status from rest_framework.decorators import api_view, permission_classes from rest_framework.response import Response # 引入你自己的模型、序列化器、权限类 @api_view(['POST']) @permission_classes([IsAuthenticated]) # 确认添加登录权限校验,避免匿名用户下单 @transaction.atomic # 开启事务,任意步骤出错自动回滚所有已写入数据 def addOrderItems(request): user = request.user data = request.data orderItems = data.get('orderItems', []) if not orderItems: return Response({'detail': 'Order item was not provided'}, status=status.HTTP_400_BAD_REQUEST) # Step 1: 创建订单 order = Order.objects.create( user=user, paymentMethod=data['paymentMethod'], ) # Step 2: 创建收货地址,补全所有字段 shipping = ShippingAddress.objects.create( order=order, address=data['shippingAddress']['address'], city=data['shippingAddress']['city'], postalCode=data['shippingAddress']['postalCode'], country=data['shippingAddress']['country'], ) # Step 3: 循环创建订单项 for i in orderItems: # 校验商品是否存在 try: product = Product.objects.get(id=i['product']) except Product.DoesNotExist: return Response({'detail': f'Product with id {i["product"]} does not exist'}, status=status.HTTP_400_BAD_REQUEST) item = OrderItem.objects.create( product=product, order=order, name=product.name, qty=i['qty'], price=i['price'], image=product.image.url, ) # Step 4: 扣减库存,修正字段名 product.stock -= item.qty product.save() serializer = OrderSerializer(order, many=False) return Response(serializer.data)
注意:如果你的
ShippingAddress模型里city、postalCode、country字段设置了null=False的非空约束,之前没传这些字段的代码本身就会抛错,创建地址的传参要和模型字段定义对齐。
内容的提问来源于stack exchange,提问作者C-Bizz
相关产品推荐
相关产品推荐

