我正在使用 Django REST Framework (DRF) 开发 RESTful API,我需要为整个应用程序中发生的各种验证错误实现通用的错误处理机制,包括但不限于 JWT 身份验证失败。
当发生验证错误时,DRF 返回默认错误响应,这些响应可能不方便用户使用,也可能在不同端点之间不一致。例如,JWT 令牌验证错误会生成如下所示的响应:
{
"detail": "Given token not valid for any token type",
"code": "token_not_valid",
"messages": [
{
"token_class": "AccessToken",
"token_type": "access",
"message": "Token is invalid or expired"
}
]
}
我希望标准化整个应用程序中的错误响应,以改善用户体验。具体来说,我想创建一个通用函数,它可以按以下格式返回所有验证错误的结构化错误响应:
{
"status": false,
"responseCode": 0,
"message": "Validation ",
"data": {}
}
我尝试创建 custom_exception_handler
def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if response is not None:
custom_response_data = {
'status': False,
'responseCode': 0,
'message': 'Validation error',
'data': {}
}
if isinstance(response.data, dict):
errors = {}
for field, detail in response.data.items():
if isinstance(detail, list):
errors[field] = detail[0] if detail else 'Invalid input.'
elif isinstance(detail, dict):
errors[field] = " | ".join(str(v) for v in detail.values())
else:
errors[field] = str(detail)
custom_response_data['message'] = " | ".join(errors.values())
custom_response_data['data'] = errors
response.data = custom_response_data
return response
但它没有给我想要的
在 DRF 中,验证全部在
serializer
内进行。在一个浅显的示例中,假设您想为给定用户生成 JWT 令牌:
模型.py
class JWTExample(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
token = models.UUIDField(default=uuid.uuid4, editable=False)
refresh_token = models.UUIDField(default=uuid.uuid4, editable=False)
views.py
class JWTCreateView(APIView):
def post(self, request, format=None):
serializer = JWTExampleSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
有两种方法可以实现 自定义验证器,即作为
function-based
验证器或作为 class-based
。为了重用,您可以将此函数/类导出到 validators.py
文件中。由于基于函数是直接的,这里是一个基于类的示例:
验证器.py
class UserValidator:
def __call__(self, value):
try:
user = get_user_model().objects.get(username=value)
except ObjectDoesNotExist:
message = {
"status": False,
"responseCode": 0,
"message": "Validation ",
"data": {},
}
raise serializers.ValidationError(message)