自定义|自定义 serializers.ValidationError 的错误返回
在使用DRF进行反序列过程中,总是需要校验字段,然后返回错误结果。可以使用默认的自定义校验项,也可以自定义校验项。而默认的自定义校验项总是差强人意。
版本
Django 2.2.3
Python 3.8.8
djangorestframework 3.13.1
目标效果
文章图片
默认错误返回效果 —— 默认校验函数
文章图片
默认错误返回 —— 默认校验函数
def validate(self, attrs):
"""
验证字段
"""
# 确认手机号是否唯一
user = User.objects.get(mobile=attrs.get('mobile'))
print(user)
if user:
raise serializers.ValidationError(detail={'status': 1, 'message': '当前手机号码已经被注册!', 'data': None})
默认错误返回效果 —— 自定义校验函数
文章图片
采用自定义校验函数之后,返回格式有所改善,但是此种返回都是以字段名为key,自定义的内容格式成为了这个key的value。
默认错误返回 —— 自定义校验函数
def validate_mobile(self, mobile):
"""
验证手机号
"""
try:
# 确认手机号是否唯一
user = User.objects.get(mobile=mobile)
print(user)
if user:
raise serializers.ValidationError(detail={'status': 1, 'message': '当前手机号码已经被注册!', 'data': None})
except User.DoesNotExist:
passreturn mobile
自定义校验函数说明
- 方法名必须以validate_作为前缀,后缀为对应的字段名:如
validate_mobile
中的mobile
即为模型的一个字段 - 一定要返回校验之后的值:
return mobile
- 不需要放在validators的列表中就可以生效(暂未理解为何意)
validate_
为前缀,而不是validated_
为前缀。Pycharm提示时会出现 validated_xxx
,此时多了一个d
自定义
ValidationError
返回# -*- coding:utf-8 -*-
# author: F0080
# Python 3.8.8
# FilePath: 项目/utils/validation_error.py,如demo/utils/validation_error.py
# FilePath可随意定义,但注意后面引入路径from django.utils.translation import ugettext_lazy as u_
from rest_framework import status
from rest_framework.exceptions import APIException, ErrorDetail
from rest_framework.utils.serializer_helpers import ReturnList, ReturnDictdef get_error_details(data, default_code=None):
if isinstance(data, list):
ret = [
get_error_details(item, default_code) for item in data
]
if isinstance(data, ReturnList):
return ReturnList(ret, serializer=data.serializer)
return ret
elif isinstance(data, dict):
ret = {
key: get_error_details(value, default_code) for key, value in data.items()
}
print(ret)
if isinstance(data, ReturnDict):
return ReturnDict(ret, serializer=data.serializer)
return retcode = getattr(data, 'code', default_code)
# 返回一个对象属性值
return ErrorDetail(data, code)class ValidationError400(APIException):
status_code = status.HTTP_400_BAD_REQUEST
default_detail = u_('Invalid input.')
default_code = 'invalid'def __init__(self, detail=None, code=None):
if detail is None:
detail = self.default_detail
if code is None:
code = self.default_code
if not isinstance(detail, dict) and not isinstance(detail, list):
detail = [detail]self.detail = get_error_details(detail, code)
在serializers.py中使用自定义
ValidationError
from demo.utils.validation_error.py import ValidationError400...
def validate_mobile(self, mobile):
"""
自定义校验函数——验证手机号
"""
try:
# 确认手机号是否唯一
user = User.objects.get(mobile=mobile)
print(user)
if user:
raise ValidationError400(detail={'status': 1, 'message': '当前手机号码已经被注册!', 'data': None})
except User.DoesNotExist:
passreturn mobiledef validate(self, attrs):
"""
默认校验函数——验证密码
"""
password = attrs.get('password')
# 验证密码长度6-16位
if not re.match('^.{6,16}$', password):
raise ValidationError400(detail={'status': 1, 'message': '密码长度必须在6-16位之间!', 'data': None})
...
致谢大佬
rest_framework serializers ValidationError 错误信息自定义 key 值
DjangoRestFramework ModelSerializer:字段级验证不起作用
推荐阅读
- IntelliJ|IntelliJ IDEA自动生成自定义的类注释和方法注释
- 如何在|如何在 Spring Boot 优雅关闭加入一些自定义机制
- SpringBoot基于redis自定义注解实现后端接口防重复提交校验
- Spring|Spring Security自定义认证逻辑实例详解
- Angular|Angular 基于自定义指令的内容投影 content projection 问题的单步调试
- 数据标注|使用LabelImg准备训练YOLO目标检测所需要的自定义数据集
- Android|Android Compose自定义TextField实现自定义的输入框
- 帅到起飞,在thymeleaf中使用自定义工具类
- PyTorch自定义损失函数
- Flink自定义HBasesink的过程