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
相关产品推荐
相关产品推荐

