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

如何在Django子序列化器中获取父模型ID?

解决Django嵌套序列化器中子序列化器获取父模型ID的问题

要在嵌套保存Parent和关联Material时自动关联父模型ID,不需要在子序列化器MaterialSerializer中手动处理,只需重写父序列化器ParentSerializer的create方法,手动创建关联关系即可:

步骤1:调整MaterialSerializer

去掉parent字段(或设置为只读),因为我们不需要从前端接收父ID,而是由后端自动关联:

class MaterialSerializer(serializers.ModelSerializer):
    class Meta:
        model = Material
        fields = ['id', 'name', 'description']
        # 如果需要在返回数据中包含parent字段,添加以下配置:
        # fields = ['id', 'name', 'description', 'parent']
        # extra_kwargs = {'parent': {'read_only': True}}

步骤2:重写ParentSerializer的create方法

在父序列化器中先创建Parent实例,再遍历嵌套的Material数据并关联到该父实例:

class ParentSerializer(serializers.ModelSerializer):
    material = MaterialSerializer(many=True)

    class Meta:
        model = Parent
        fields = ['name', 'date', 'material']

    def create(self, validated_data):
        # 提取嵌套的Material数据
        materials_data = validated_data.pop('material')
        # 创建Parent主实例
        parent = Parent.objects.create(**validated_data)
        # 批量创建关联的Material,自动绑定parent_id
        for material_data in materials_data:
            Material.objects.create(parent=parent, **material_data)
        return parent

补充:如果需要在子序列化器中访问父实例(如验证逻辑)

如果你的业务需要在MaterialSerializer中基于父模型做验证或其他逻辑,可以通过context传递父实例。比如在父序列化器的update方法中(此时父实例已存在):

class ParentSerializer(serializers.ModelSerializer):
    material = MaterialSerializer(many=True)

    def update(self, instance, validated_data):
        materials_data = validated_data.pop('material')
        # 将父实例传入子序列化器的context
        for material_data in materials_data:
            serializer = MaterialSerializer(data=material_data, context={'parent': instance})
            serializer.is_valid(raise_exception=True)
            serializer.save(parent=instance)
        # 更新父实例字段
        instance.name = validated_data.get('name', instance.name)
        instance.date = validated_data.get('date', instance.date)
        instance.save()
        return instance

然后在MaterialSerializer中可以通过self.context.get('parent')获取父实例:

class MaterialSerializer(serializers.ModelSerializer):
    class Meta:
        model = Material
        fields = ['id', 'name', 'description', 'parent']

    def validate_name(self, value):
        parent = self.context.get('parent')
        # 基于父实例做验证逻辑,比如检查同名Material是否存在
        if Material.objects.filter(parent=parent, name=value).exists():
            raise serializers.ValidationError(f"该父项已存在名为{value}的物料")
        return value

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 19:32:39