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

Django Rest Framework中Book与Genres多对多关系POST请求报错问题咨询

解决DRF多对多嵌套序列化POST请求报错问题

这个问题在DRF处理多对多关联时太常见了——默认的.create()方法确实不会自动处理可写的嵌套字段,咱们直接通过重写序列化器的create方法来解决:

第一步:修改BookSerial序列化器,重写create方法

核心思路是先创建Book实例,再单独处理嵌套的Genres关联数据,避开DRF默认逻辑处理不了嵌套多对多的问题。修改后的serializer.py代码如下:

class GenreSerial(serializers.ModelSerializer):
    class Meta:
        model = Genres
        fields = ['name']

class BookSerial(serializers.ModelSerializer):
    genre = GenreSerial(source="bookgenres", many=True)

    class Meta:
        model = Book
        fields = '__all__'

    def create(self, validated_data):
        # 从验证后的数据中取出嵌套的分类数据(注意这里用的是source对应的字段名`bookgenres`)
        genres_data = validated_data.pop('bookgenres')
        # 先创建Book主实例
        book = Book.objects.create(**validated_data)
        # 遍历分类数据,创建或获取已存在的分类实例,再关联到当前书籍
        for genre_data in genres_data:
            # 使用get_or_create避免重复创建相同名称的分类
            genre, _ = Genres.objects.get_or_create(name=genre_data['name'])
            book.bookgenres.add(genre)
        return book

第二步:确认POST请求的格式

你的POST请求体需要和序列化器的字段对应,示例JSON如下:

{
    "title": "沙丘",
    "description": "一部经典科幻小说",
    "alternative_name": "Dune",
    "author": "弗兰克·赫伯特",
    "blacklist": false,
    "genre": [
        {"name": "科幻"},
        {"name": "文学"}
    ]
}

补充说明

  • 如果你的业务逻辑允许分类重复,可以把get_or_create换成create,但通常多对多的分类是唯一的,所以get_or_create更合理。
  • 如果你不需要通过POST创建关联分类,也可以直接给genre字段加read_only=True,但这显然不是你想要的解决方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 11:42:47