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

Django Rest Framework多对多字段序列化问题求解

问题解决:Django REST Framework多对多字段序列化报错处理

问题背景

现有Django模型MaterialAttribute和MaterialType(多对多关联),需要实现MaterialTypeSerializer满足:

  • 列表/详情接口返回attributes的完整JSON结构(包含id和name)
  • 创建/更新时接收attributes的主键列表
    当前实现自定义MaterialAttributeManyField继承PrimaryKeyRelatedField并重写to_representation返回序列化后的字典,运行时出现unhashable type: 'ReturnDict'错误,要求不重写create和update方法解决。

错误原因

PrimaryKeyRelatedField内部处理多对多关系时,依赖返回的可哈希值(默认是主键)来做数据匹配与存储。自定义字段中to_representation返回了MaterialAttributeSerializer生成的ReturnDict(不可哈希类型),导致DRF内部处理逻辑出错。

简洁解决方案

不需要自定义字段,直接在MaterialTypeSerializer中重写to_representation方法,实现输入用主键、输出用完整结构的分离,同时保留DRF原生的多对多字段处理逻辑:

class MaterialAttributeSerializer(serializers.ModelSerializer):
    """
    Serializer for MaterialAttribute model
    """
    class Meta:
        model = MaterialAttribute
        fields = ["id", "name"]


class MaterialTypeSerializer(serializers.ModelSerializer):
    """
    Serializer for MaterialType model
    - 输入:接收attributes主键列表
    - 输出:返回attributes完整JSON结构
    """
    attributes = serializers.PrimaryKeyRelatedField(
        queryset=MaterialAttribute.objects.all(),
        many=True
    )

    class Meta:
        model = MaterialType
        fields = ["id", "name", "attributes"]

    def to_representation(self, instance):
        # 先调用父类获取基础序列化数据
        data = super().to_representation(instance)
        # 将attributes字段替换为完整的序列化结构
        data["attributes"] = MaterialAttributeSerializer(
            instance.attributes.all(),
            many=True
        ).data
        return data

效果说明

  • 创建/更新:直接传入attributes主键列表(如{"name": "Test", "attributes": [1,2]}),DRF通过PrimaryKeyRelatedField自动验证并处理多对多关系的保存,无需重写create/update。
  • 列表/详情返回:to_representation方法会自动将attributes替换为包含id和name的完整JSON结构,符合需求示例。

补充说明

若需要兼容用户提供的创建示例格式(数组内为包含主键的对象,如[{"id":1}, {"id":2}]),只需将PrimaryKeyRelatedField调整为:

attributes = serializers.PrimaryKeyRelatedField(
    queryset=MaterialAttribute.objects.all(),
    many=True,
    source="id"
)

但更规范的做法是直接传递主键数组,上述基础方案已覆盖标准场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:56:01