You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:59:39