DRF中如何获取嵌套序列化器字段执行自定义校验?
问题原因
你在DetailSerializer中将master嵌套序列化器设置为read_only=True,该字段仅会在序列化返回响应时生效,不会处理前端提交的反序列化输入,因此validate方法的attrs参数中不会包含master相关数据,自然无法直接获取date_signed字段。
解决方案
保留原有只读嵌套序列化器用于返回关联主表完整信息,额外新增一个可写的外键主键字段接收前端提交的关联MasterID,在校验逻辑中通过主键查询获取Master实例即可拿到date_signed字段,同时兼容创建、更新两种业务场景。
完整修正后的序列化器代码
from rest_framework import serializers from rest_framework.exceptions import ValidationError from .models import Master, Detail class MasterSerializer(serializers.ModelSerializer): class Meta: model = Master fields = ['id','date_signed','info1','info2'] class DetailSerializer(serializers.ModelSerializer): # 保留只读嵌套序列化器,用于返回响应时带出master完整信息 master = MasterSerializer(read_only=True) # 新增可写外键字段,用于接收前端提交的master关联ID,仅在反序列化时生效 master_id = serializers.PrimaryKeyRelatedField( queryset=Master.objects.all(), write_only=True, source='master' # 指定映射到模型的master字段 ) class Meta: model = Detail fields = ['id','master','master_id','date_start','date_end','info3','info4'] def validate(self, attrs): # 兼容部分更新场景,优先取attrs中的新值,没有则取现有实例的值 date_start = attrs.get('date_start', self.instance.date_start if self.instance else None) date_end = attrs.get('date_end', self.instance.date_end if self.instance else None) # 校验date_start早于date_end if date_start >= date_end: raise ValidationError('开始日期必须早于结束日期') # 获取master实例:优先取attrs中新提交的,没有则取现有实例关联的master master = attrs.get('master', self.instance.master if self.instance else None) # 校验master的date_signed早于detail的date_start if master.date_signed >= date_start: raise ValidationError('主表签署日期必须早于明细开始日期') return attrs
使用说明
前端提交创建/更新请求时,只需传master_id字段对应关联的Master主键即可,接口返回时会自动带出master嵌套的完整信息,无需额外处理。
内容的提问来源于stack exchange,提问作者theRoad
相关产品推荐
相关产品推荐

