Django Rest Framework中通过ID传递模型实例的序列化问题
解决DRF序列化器提交product_id返回product为null的问题
我之前也碰到过一模一样的问题,核心原因是你当前的序列化器字段设计和提交的参数不匹配,导致DRF无法正确关联商品对象。
问题根源
你的CartSerializer里把product定义成了嵌套的ProductSerializer,这意味着:
- 当你从后台管理添加购物车时,是直接选择商品对象,序列化器能正确识别并关联,返回时也能序列化出完整的商品详情;
- 但在Postman提交
product_id时,DRF不会自动把这个product_id映射到product外键字段,validated_data里根本没有product相关数据,创建出来的Cart实例自然product为null,返回结果也就显示null了。
解决方案:拆分读写字段
我们可以给序列化器添加一个仅用于写入的product_id字段,同时把原有的product字段设为仅用于读取,这样既能接收前端传入的商品ID,又能返回完整的商品详情:
from rest_framework import serializers from .models import Cart, Product class CartSerializer(serializers.ModelSerializer): # 仅用于返回时序列化商品详情,设置为只读 product = ProductSerializer(read_only=True) # 仅用于接收前端传入的商品ID,必填且只写 product_id = serializers.IntegerField(write_only=True, required=True) class Meta: model = Cart fields = ['id', 'user', 'product', 'product_id', 'quantity'] def create(self, validated_data): # 从验证后的数据中取出product_id product_id = validated_data.pop('product_id') try: # 获取对应的商品实例 product = Product.objects.get(id=product_id) except Product.DoesNotExist: # 如果商品不存在,抛出验证错误 raise serializers.ValidationError({"product_id": "指定的商品不存在"}) # 创建购物车实例并关联商品 return Cart.objects.create(product=product, **validated_data)
测试方式
修改后,在Postman里提交的请求体应该是这样的:
{ "user": 26, "product_id": 8, "quantity": 1 }
这样返回的结果就会和后台添加时一致,product字段会显示完整的商品详情。
另一种简洁写法(可选)
如果不需要手动校验商品是否存在(DRF会自动用queryset校验),也可以用PrimaryKeyRelatedField来简化:
class CartSerializer(serializers.ModelSerializer): product = ProductSerializer(read_only=True) # 用PrimaryKeyRelatedField接收商品ID,自动校验存在性 product_id = serializers.PrimaryKeyRelatedField( queryset=Product.objects.all(), write_only=True, source='product' ) class Meta: model = Cart fields = ['id', 'user', 'product', 'product_id', 'quantity'] # 这里可以不用重写create,DRF会自动把product_id映射到product外键 def create(self, validated_data): return Cart.objects.create(**validated_data)
这个写法更简洁,PrimaryKeyRelatedField会自动验证传入的ID是否存在于Product表中,省去了手动捕获异常的代码。
内容的提问来源于stack exchange,提问作者Nerd
相关产品推荐
相关产品推荐

