74 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
 | 
						|
"""
 | 
						|
@author: 猿小天
 | 
						|
@contact: QQ:1638245306
 | 
						|
@Created on: 2021/6/2 002 17:03
 | 
						|
@Remark: 自定义验证器
 | 
						|
"""
 | 
						|
 | 
						|
from django.db import DataError
 | 
						|
from rest_framework.exceptions import APIException
 | 
						|
from rest_framework.validators import UniqueValidator
 | 
						|
 | 
						|
 | 
						|
class CustomValidationError(APIException):
 | 
						|
    """
 | 
						|
    继承并重写验证器返回的结果,避免暴露字段
 | 
						|
    """
 | 
						|
 | 
						|
    def __init__(self, detail):
 | 
						|
        self.detail = detail
 | 
						|
 | 
						|
 | 
						|
def qs_exists(queryset):
 | 
						|
    try:
 | 
						|
        return queryset.exists()
 | 
						|
    except (TypeError, ValueError, DataError):
 | 
						|
        return False
 | 
						|
 | 
						|
 | 
						|
def qs_filter(queryset, **kwargs):
 | 
						|
    try:
 | 
						|
        return queryset.filter(**kwargs)
 | 
						|
    except (TypeError, ValueError, DataError):
 | 
						|
        return queryset.none()
 | 
						|
 | 
						|
 | 
						|
class CustomUniqueValidator(UniqueValidator):
 | 
						|
    """
 | 
						|
    继承,重写必填字段的验证器结果,防止字段暴露
 | 
						|
    """
 | 
						|
 | 
						|
    def filter_queryset(self, value, queryset, field_name):
 | 
						|
        """
 | 
						|
        Filter the queryset to all instances matching the given attribute.
 | 
						|
        """
 | 
						|
        filter_kwargs = {'%s__%s' % (field_name, self.lookup): value}
 | 
						|
        return qs_filter(queryset, **filter_kwargs)
 | 
						|
 | 
						|
    def exclude_current_instance(self, queryset, instance):
 | 
						|
        """
 | 
						|
        If an instance is being updated, then do not include
 | 
						|
        that instance itself as a uniqueness conflict.
 | 
						|
        """
 | 
						|
        if instance is not None:
 | 
						|
            return queryset.exclude(pk=instance.pk)
 | 
						|
        return queryset
 | 
						|
 | 
						|
    def __call__(self, value, serializer_field):
 | 
						|
        # Determine the underlying model field name. This may not be the
 | 
						|
        # same as the serializer field name if `source=<>` is set.
 | 
						|
        field_name = serializer_field.source_attrs[-1]
 | 
						|
        # Determine the existing instance, if this is an update operation.
 | 
						|
        instance = getattr(serializer_field.parent, 'instance', None)
 | 
						|
 | 
						|
        queryset = self.queryset
 | 
						|
        queryset = self.filter_queryset(value, queryset, field_name)
 | 
						|
        queryset = self.exclude_current_instance(queryset, instance)
 | 
						|
        if qs_exists(queryset):
 | 
						|
            raise CustomValidationError(self.message)
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        return super().__repr__()
 |