Django DRF序列化器设置depth=1时如何正常POST创建数据
问题根源
DRF序列化器的depth参数仅用于控制嵌套序列化的只读输出深度,当设置depth≥1时,所有外键、多对多关联字段都会被自动替换为只读的嵌套序列化器,不会接收前端传入的主键值作为写入参数。此时传入的course_name:3、student:1会被序列化器忽略,最终写入数据库时外键字段为空,触发非空约束报错。
尝试的course_name.id这类点语法传参本身也不被DRF默认支持,加之外键字段已被设为只读,自然无法正常创建记录。
最优实现方案
不建议强行让depth=1的序列化器同时支持写入,最稳妥、最符合DRF设计规范的方案是在同一个序列化器中显式区分读写字段,既保留GET请求的嵌套返回结构,又支持POST时传入外键ID创建记录,代码如下:
from rest_framework import serializers from .models import Course, CourseEnrolment, UserAccount from datetime import datetime # 关联模型的简要只读序列化器,用于GET时嵌套返回 class CourseBriefSerializer(serializers.ModelSerializer): class Meta: model = Course fields = ['id', 'name', 'description', 'prerequisite', 'fee'] read_only_fields = fields class UserBriefSerializer(serializers.ModelSerializer): class Meta: model = UserAccount fields = ['id', 'email', 'first_name', 'last_name', 'phone'] read_only_fields = fields class CourseEnrolmentSerializer(serializers.ModelSerializer): # 只读嵌套字段,GET请求时返回关联详情 course_name = CourseBriefSerializer(read_only=True) student = UserBriefSerializer(read_only=True) # 只写字段,POST/PUT时接收前端传的外键ID course_id = serializers.PrimaryKeyRelatedField( queryset=Course.objects.all(), write_only=True, source='course_name' # 写入时自动映射到course_name外键字段 ) student_id = serializers.PrimaryKeyRelatedField( queryset=UserAccount.objects.all(), write_only=True, source='student' # 写入时自动映射到student外键字段 ) class Meta: model = CourseEnrolment fields = [ 'id', 'schedule', 'enrolment_date', 'course_name', 'student', 'course_id', 'student_id' ]
调用方式
POST创建选课记录时传参格式如下:
{ "course_id": 3, "schedule": "June 23, 2022", "student_id": 1 }
GET请求返回的结构和之前用depth=1得到的结果完全一致,不需要调整前端的列表/详情页解析逻辑。
额外注意事项
模型里的enrolment_date字段存在写法问题:
# 错误写法:服务启动时就会固定时间,所有记录的报名时间都一样 enrolment_date = models.DateTimeField(default=datetime.now()) # 正确写法:传函数引用,创建记录时才会调用生成当前时间 enrolment_date = models.DateTimeField(default=datetime.now)
可选替代方案
如果不想修改序列化器字段,也可以在视图层根据请求方法选择不同的序列化器:
- GET请求使用带
depth=1的序列化器返回嵌套数据 - POST/PUT/PATCH请求使用不带
depth的基础序列化器接收外键ID
但这种方案会让前后端字段逻辑不统一,优先推荐前面的同序列化器区分读写字段的实现。
内容的提问来源于stack exchange,提问作者Mart
相关产品推荐
相关产品推荐

