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__()
|