DRF创建关联ManyToManyField的Rant对象时报错,求排查解决
问题原因及解决方案
核心问题
错误提示"Expected a list of items but got type \"str\""指向两个关键问题:
- 传入的
categories参数是字符串类型,而序列化器要求必须是列表格式 - 若你是要关联已存在的分类,当前用嵌套
CategorySerializer的写法并不适配创建场景
解决方案分两种场景
场景1:关联已存在的Category
如果需求是给新创建的Rant关联已有的分类,无需创建新分类,修改序列化器如下:
class RantSerializer(serializers.ModelSerializer): # 用PrimaryKeyRelatedField接收分类ID列表 categories = serializers.PrimaryKeyRelatedField(many=True, queryset=Category.objects.all()) class Meta: model = Rant fields = ('rant', 'slug', 'categories')
此时POST请求的数据格式需为:
{ "rant": "你的吐槽内容", "slug": "your-slug", "categories": [1, 3] // 填入已存在的Category的ID列表 }
场景2:创建Rant的同时创建新Category
如果需要在创建Rant时一并生成新分类,必须重写序列化器的create方法(默认序列化器无法处理多对多关系的嵌套创建),修改后的代码:
class CategorySerializer(serializers.ModelSerializer): class Meta: model = Category fields = "__all__" class RantSerializer(serializers.ModelSerializer): categories = CategorySerializer(many=True) class Meta: model = Rant fields = ('rant', 'slug', 'categories') def create(self, validated_data): # 提取分类数据 categories_data = validated_data.pop('categories') # 创建Rant主对象 rant = Rant.objects.create(**validated_data) # 遍历分类数据,创建或获取分类后关联到Rant for category_data in categories_data: category, _ = Category.objects.get_or_create(**category_data) rant.categories.add(category) return rant
此时POST请求的数据必须是分类对象的列表,不能是单个字符串:
{ "rant": "你的吐槽内容", "slug": "your-slug", "categories": [ {"name": "分类1"}, {"name": "分类2"} ] }
额外检查
无论哪种场景,都要确保POST请求的categories参数是数组格式,绝对不能传入单个字符串(比如"categories": "分类1"这种写法是错误的)。
内容的提问来源于stack exchange,提问作者Vicente Antonio G. Reyes
相关产品推荐
相关产品推荐

