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

DRF Course序列化器多对多字段创建报错与嵌套联系人返回方案

问题根源

你的代码共有4处核心错误,直接导致POST请求报错、返回数据不符合预期:

  • 多对多数据处理逻辑错误:循环处理联系人时,对列表类型的contacts_data调用pop('id'),列表仅支持整数索引pop,传入字符串'id'直接触发类型错误,是你运行时报错的直接原因
  • 关联操作写法错误:Contact.objects.get_or_create()返回值是(模型实例, 是否新建标记)的二元元组,你没有解包直接使用;且最后course.contacts.add()仅传入单个对象、参数格式错误,也完全没处理branches字段的关联逻辑
  • 序列化器配置错误:默认ModelSerializer对多对多字段仅返回主键ID,没有配置嵌套序列化逻辑,导致返回结果只有联系人/分支ID,没有完整字段
  • 视图笔误:CourseDetailView的delete方法中误写为self.get.get_object(pk),多写了一层.get,调用删除接口时会触发属性错误
修复方案

直接替换对应代码即可:

1. 修正序列化器代码

替换原有的序列化器代码为以下内容:

from rest_framework import serializers
from application.category.models import Category, Branch, Contact, Course


class CategorySerializers(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'


class BranchSerializer(serializers.ModelSerializer):
    class Meta:
        model = Branch
        fields = '__all__'


class ContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = Contact
        fields = '__all__'


class CourseSerializer(serializers.ModelSerializer):
    # 写入时接收已存在的联系人/分支ID列表
    contacts = serializers.PrimaryKeyRelatedField(
        many=True, queryset=Contact.objects.all()
    )
    branches = serializers.PrimaryKeyRelatedField(
        many=True, queryset=Branch.objects.all(), required=False
    )

    class Meta:
        model = Course
        fields = '__all__'

    def create(self, validated_data):
        # 取出多对多关联数据
        contacts_data = validated_data.pop('contacts')
        branches_data = validated_data.pop('branches', [])
        # 先创建Course主表记录
        course = Course.objects.create(**validated_data)
        # 批量绑定多对多关联
        course.contacts.set(contacts_data)
        course.branches.set(branches_data)
        return course

    def to_representation(self, instance):
        # 输出序列化结果时,替换为完整嵌套对象数据,而非仅返回ID
        rep = super().to_representation(instance)
        rep['contacts'] = ContactSerializer(instance.contacts.all(), many=True).data
        rep['branches'] = BranchSerializer(instance.branches.all(), many=True).data
        return rep

2. 修正视图笔误

找到CourseDetailView的delete方法,替换为以下代码:

def delete(self, request, pk):
    course = self.get_object(pk)
    course.delete()
    return Response(f'{course} was deleted!', status=status.HTTP_204_NO_CONTENT)

3. 接口调用说明

POST请求创建Course时,请求体按以下格式传参,contacts/branches传已存在的记录ID数组即可:

{
    "name": "Python入门课程",
    "description": "面向零基础学员的Python系统教学",
    "category": 1,
    "logo": "python_basic.png",
    "contacts": [1, 3],
    "branches": [1, 2]
}

创建成功后接口会自动返回完整的联系人、分支对象详情,不再只返回ID列表。

内容的提问来源于stack exchange,提问作者Антон Ращупкин

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 09:48:22