Django退款API报错:Refund.order必须为Order实例而非ID值
解决Django退款API的ValueError问题:Cannot assign "X": "Refund.order" must be a "Order" instance
核心问题原因
你的RefundOrderSerializer的save方法中,直接将整数类型的order_id赋值给了refund.order(外键字段),但Django的外键字段要求赋值的是Order模型实例,或者通过外键的_id后缀属性直接赋值id值。
同时序列化器还存在两个额外问题:
message和email未作为序列化器字段定义,无法从请求数据中获取save方法返回的是Refund实例,但views里用OrderSerializer序列化,逻辑不匹配
修正后的代码
serializers.py
class RefundOrderSerializer(serializers.Serializer): order_id = serializers.IntegerField() # 新增message和email字段,接收请求数据 message = serializers.CharField(max_length=500) email = serializers.EmailField() def validate_order_id(self, order_id): if not Order.objects.filter(pk=order_id).exists(): raise serializers.ValidationError('未找到对应ID的订单') # 返回Order实例,后续直接赋值外键 return Order.objects.get(pk=order_id) def save(self, **kwargs): with transaction.atomic(): # 此时order是Order实例,不是整数id order = self.validated_data['order_id'] message = self.validated_data['message'] email = self.validated_data['email'] refund = Refund() refund.order = order refund.reason = message refund.email = email refund.save() # 返回order实例,匹配views中用OrderSerializer序列化的逻辑 return order
可选方案(不提前获取实例)
如果不想提前查询Order实例,也可以直接给外键的_id属性赋值:
# 在save方法中替换外键赋值的行 refund.order_id = self.validated_data['order_id'] # 注意此时validate_order_id返回的是整数id,需对应修改validate方法的返回值
额外修正点
validate_order_id方法中存在拼写错误:exist()改为exists()- 建议在validate阶段增加权限验证(比如当前用户是否有权限申请该订单的退款)
- views中
create方法返回OrderSerializer(order),因此save方法返回order实例更合理
内容的提问来源于stack exchange,提问作者Sesshōmaru
相关产品推荐
相关产品推荐

