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

DRF序列化器如何创建外键模型数据?报反向关联直接赋值错误

报错原因

该报错触发的核心原因是items属于ConsignmentNote模型的反向关联集合(即ConsignmentItem模型通过外键指向ConsignmentNote时设置的related_name为items),Django ORM不允许在创建主表记录时直接对反向关联集合赋值,必须先完成主表记录创建,再单独处理关联子表数据的写入。
你的现有代码还存在两个额外问题:

  • 重复定义了两次create_user字段,前一个用于写入当前登录用户的HiddenField会被后一个read_only的UserSerializer完全覆盖,无法自动注入当前操作人
  • 序列化器未定义可写的contragent外键字段,仅配置了只读的contragent_detail,无法接收请求中传递的往来单位参数
修正步骤

1. 调整序列化器字段配置

修正重复字段问题,补全可写外键字段:

class ConsignmentNoteSerializer(serializers.ModelSerializer):
    # 写入用:自动注入当前登录用户,映射到模型的creator字段
    create_user = serializers.HiddenField(default=serializers.CurrentUserDefault(), source='creator')
    # 读用:返回关联的用户、往来单位详情
    creator_info = UserSerializer(source='creator', read_only=True)
    contragent_detail = ContragentSerializer(source='contragent', read_only=True)
    # 可写外键:接收往来单位主键值
    contragent = serializers.PrimaryKeyRelatedField(queryset=Contragent.objects.all())
    items = ConsignmentItemSerializer(many=True)

    class Meta:
        model = ConsignmentNote
        fields = ['id', 'doc_type', 'date', 'number', 'contragent', 'contragent_detail', 'comment', 'create_user', 'creator_info', 'items', 'created']

2. 重写正确的create方法

按照「先创建主表、再批量创建子表关联数据」的逻辑实现:

def create(self, validated_data):
    # 先弹出嵌套的商品明细数据
    items_data = validated_data.pop('items')
    # 创建销货单主记录
    consignment_note = ConsignmentNote.objects.create(**validated_data)
    # 循环创建所有商品明细,绑定外键关联到刚创建的销货单
    for item_data in items_data:
        # 注意:如果你的ConsignmentItem模型中关联ConsignmentNote的外键字段名不是consignment_note,请替换为实际字段名
        ConsignmentItem.objects.create(consignment_note=consignment_note, **item_data)
    return consignment_note

3. 调整请求参数格式

对应序列化器的字段名调整请求JSON,创建场景不需要传自增id,去掉多余的尾逗号:

{
    "doc_type": "capitalize",
    "date": "2022-06-04",
    "number": 98,
    "contragent": 4,
    "comment": "",
    "items": [
        {
            "product": 10,
            "buy_price": "200.00",
            "sell_price": "500.00",
            "quantity": 5
        }
    ]
}

补充说明:如果后续需要实现更新接口,处理嵌套items数据时,对已经存在的item可以调用consignment_note.items.set(目标明细列表)完成关联,也可以逐个做新增、修改、删除的判断处理。

内容的提问来源于stack exchange,提问作者sk1p

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 08:33:20