Django REST Framework序列化器:按状态控制字段显示的自定义验证
当然可以实现!在Django REST Framework(DRF)里,我们可以通过动态控制字段可见性和自定义验证规则,完美实现根据患者就诊状态显示特定字段的需求。下面给你一步步拆解具体方案:
1. 动态控制返回给前端的字段(序列化阶段)
如果你想让不同状态的就诊记录,在前端展示不同的字段,可以重写序列化器的to_representation方法。这个方法负责把模型实例转化为前端能接收的JSON数据,我们可以在这里根据status过滤字段:
from rest_framework import serializers from .models import Visit class VisitSerializer(serializers.ModelSerializer): class Meta: model = Visit # 先列出所有可能用到的字段,后续再根据状态过滤 fields = [ 'patient', 'status', 'status_time', 'visit_start_time', 'discharge_notes', 'discharged', 'admitted', 'visit_duration', 'session_start_time', 'session_end_time', 'check_in', 'check_out' ] def to_representation(self, instance): # 先获取默认的序列化数据 data = super().to_representation(instance) # 根据就诊状态筛选要返回的字段 if instance.status == 'ARRIVED': # ARRIVED状态下只保留指定字段 allowed_fields = ['patient', 'status', 'status_time', 'visit_start_time'] elif instance.status == 'COMPLETE': # COMPLETE状态下展示出院相关字段 allowed_fields = ['patient', 'status', 'status_time', 'discharge_notes', 'visit_duration', 'session_end_time'] elif instance.status == 'CANCELLED': # 取消状态下可以只保留基础信息 allowed_fields = ['patient', 'status', 'status_time'] else: # 其他状态默认返回所有字段,或者自定义规则 allowed_fields = list(data.keys()) # 移除不在允许列表中的字段 for field in list(data.keys()): if field not in allowed_fields: del data[field] return data
这个方法的优势是简单直接,完全控制前端能看到的内容,适合展示类场景。
2. 添加自定义字段验证(反序列化阶段)
如果还要确保前端提交的数据符合状态规则(比如ARRIVED状态下不能提交出院记录),可以重写序列化器的validate方法,在数据存入数据库前做校验:
def validate(self, data): # 获取当前就诊状态(兼容创建和更新场景) status = data.get('status') if not status and self.instance: status = self.instance.status if status == 'ARRIVED': # 禁止提交出院相关字段 forbidden_fields = ['discharge_notes', 'discharged', 'session_end_time'] for field in forbidden_fields: if field in data: raise serializers.ValidationError(f"状态为ARRIVED时,不能提交字段 {field}") # 确保必填字段存在 if 'visit_start_time' not in data: raise serializers.ValidationError("状态为ARRIVED时,必须填写visit_start_time字段") elif status == 'COMPLETE': # 完成状态下必须提交出院记录 if 'discharge_notes' not in data or not data['discharge_notes'].strip(): raise serializers.ValidationError("状态为COMPLETE时,必须填写discharge_notes字段") return data
这样就能避免前端提交不符合状态的非法数据,保证数据库数据的一致性。
3. 视图层动态调整序列化器字段(更灵活的场景)
如果需要在视图层面根据请求或实例状态,动态调整序列化器的可用字段(不管是输入还是输出),可以在ViewSet里重写get_serializer方法:
from rest_framework import viewsets class VisitViewSet(viewsets.ModelViewSet): queryset = Visit.objects.all() serializer_class = VisitSerializer def get_serializer(self, *args, **kwargs): serializer = super().get_serializer(*args, **kwargs) instance = kwargs.get('instance') if instance: # 根据实例状态动态修改序列化器的字段 if instance.status == 'ARRIVED': serializer.fields = { 'patient': serializer.fields['patient'], 'status': serializer.fields['status'], 'status_time': serializer.fields['status_time'], 'visit_start_time': serializer.fields['visit_start_time'] } elif instance.status == 'COMPLETE': serializer.fields = { 'patient': serializer.fields['patient'], 'status': serializer.fields['status'], 'status_time': serializer.fields['status_time'], 'discharge_notes': serializer.fields['discharge_notes'], 'visit_duration': serializer.fields['visit_duration'] } return serializer
这种方式适合需要对输入输出字段做统一控制的场景,比如某个状态下前端既不能看到也不能提交某些字段。
内容的提问来源于stack exchange,提问作者Philip Mutua
相关产品推荐
相关产品推荐

