Django Rest Framework序列化器如何实现两字段二选一必填校验
实现方案
第一步:调整字段基础配置
先把两个字段都改为非必填,移除addressid的source配置避免和模型字段映射冲突:
- 两个字段都设置
required=False、allow_null=True,取消默认的必填校验 addressid不需要绑定模型字段,作为独立的入参字段使用
第二步:添加全局校验逻辑
重写序列化器的validate方法,实现二选一的条件校验:
- 校验规则:两个字段不能同时为空,也不能同时传入
- 不符合规则直接抛出
serializers.ValidationError
第三步:重写create方法处理业务逻辑
根据入参情况处理address字段的赋值:
- 传入
addressid时:直接查询对应的地址实例绑定到订单 - 传入
address嵌套数据时:先调用地址序列化器创建新的地址实例,再绑定到订单
修改后完整代码如下:
from rest_framework import serializers from .models import Order, Address # 注意你原代码中的AdressSerializer拼写可能有误,这里统一为Address class OrderSerializer(serializers.ModelSerializer): class Meta: model = Order exclude = ['in_calculation','canceled',] read_only_fields = ['id','user','status','costs'] # 调整字段配置,均设为非必填 address = AddressSerializer(required=False, allow_null=True) addressid = serializers.CharField(required=False, allow_null=True) def validate(self, attrs): # 二选一校验 has_address = attrs.get('address') is not None has_addressid = attrs.get('addressid') is not None if not has_address and not has_addressid: raise serializers.ValidationError("请传入地址ID或新地址信息") if has_address and has_addressid: raise serializers.ValidationError("地址ID和新地址信息只能传入其中一个") return attrs def create(self, validated_data): # 移除不需要的addressid字段,避免写入模型报错 address_id = validated_data.pop('addressid', None) address_data = validated_data.pop('address', None) # 处理地址逻辑 if address_id: # 传入地址ID的情况,查询已有地址 address = Address.objects.get(id=address_id) validated_data['address'] = address else: # 传入新地址的情况,先创建地址 address_serializer = AddressSerializer(data=address_data) address_serializer.is_valid(raise_exception=True) address = address_serializer.save() validated_data['address'] = address # 正常创建订单 return super().create(validated_data)
补充说明
如果需要支持PUT更新场景,参照同样的逻辑重写update方法即可。
地址查询的部分可以根据你的业务需求添加权限校验,比如校验地址是否属于当前登录用户。
内容的提问来源于stack exchange,提问作者Rune
相关产品推荐
相关产品推荐

