Django序列化器中调用update_or_create触发唯一约束校验错误如何解决
问题原因
DRF的ModelSerializer会自动读取模型中定义的unique_together联合唯一约束,生成对应的UniqueTogetherValidator校验规则,这套校验逻辑会在create()方法执行前触发,因此你还没走到自定义的update_or_create逻辑就被校验拦截报错。
解决方案
方案1:清空序列化器自动生成的校验器
直接在序列化器的Meta类中显式指定validators为空列表,覆盖默认生成的联合唯一校验即可,同时注意修正update_or_create的返回值处理:
class ActivatedCapacitySerializer(serializers.ModelSerializer): user_id = serializers.IntegerField(required=False) capacity_id = serializers.IntegerField(required=False) class Meta: model = ActivatedCapacity fields = ('user_id', 'capacity_id', 'active') # 新增此行,清空自动生成的校验规则,跳过联合唯一校验 validators = [] def create(self, validated_data): # update_or_create返回(实例对象, 是否新创建)的元组,需要取第一个值返回 activated_capacity, _ = ActivatedCapacity.objects.update_or_create( user_id=validated_data['user_id'], capacity_id=validated_data['capacity_id'], defaults = { 'active': validated_data['active'] } ) return activated_capacity
方案2:重写方法仅移除联合唯一校验
如果你不想清空所有自动生成的校验规则,只想针对性移除联合唯一校验,可以重写get_unique_together_validators方法:
class ActivatedCapacitySerializer(serializers.ModelSerializer): user_id = serializers.IntegerField(required=False) capacity_id = serializers.IntegerField(required=False) class Meta: model = ActivatedCapacity fields = ('user_id', 'capacity_id', 'active') # 重写该方法,返回空列表即可关闭联合唯一校验 def get_unique_together_validators(self): return [] def create(self, validated_data): activated_capacity, _ = ActivatedCapacity.objects.update_or_create( user_id=validated_data['user_id'], capacity_id=validated_data['capacity_id'], defaults = { 'active': validated_data['active'] } ) return activated_capacity
注意事项
移除默认校验后需要自行保证传入的user_id、capacity_id参数的合法性,避免非法数据写入数据库。
内容的提问来源于stack exchange,提问作者Henrique Andrade
相关产品推荐
相关产品推荐

