MaxKB/apps/common/handle/handle_exception.py

96 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# coding=utf-8
"""
@project: qabot
@Author
@file handle_exception.py
@date2023/9/5 19:29
@desc:
"""
import logging
import traceback
from rest_framework.exceptions import ValidationError, ErrorDetail, APIException
from rest_framework.views import exception_handler
from common.exception.app_exception import AppApiException
from django.utils.translation import gettext_lazy as _
from common.result import result
from common.utils.logger import maxkb_logger
def to_result(key, args, parent_key=None):
"""
将校验异常 args转换为统一数据
:param key: 校验key
:param args: 校验异常参数
:param parent_key 父key
:return: 接口响应对象
"""
error_detail = list(filter(
lambda d: True if isinstance(d, ErrorDetail) else True if isinstance(d, dict) and len(
d.keys()) > 0 else False,
(args[0] if len(args) > 0 else {key: [ErrorDetail(_('Unknown exception'), code='unknown')]}).get(key)))[0]
if isinstance(error_detail, dict):
return list(map(lambda k: to_result(k, args=[error_detail],
parent_key=key if parent_key is None else parent_key + '.' + key),
error_detail.keys() if len(error_detail) > 0 else []))[0]
return result.Result(500 if isinstance(error_detail.code, str) else error_detail.code,
message=f"{key if parent_key is None else parent_key + '.' + key}】为必填参数" if str(
error_detail) == "This field is required." else error_detail)
def validation_error_to_result(exc: ValidationError):
"""
校验异常转响应对象
:param exc: 校验异常
:return: 接口响应对象
"""
try:
v = find_err_detail(exc.detail)
if v is None:
return result.error(str(exc.detail))
return result.error(str(v))
except Exception as e:
return result.error(str(exc.detail))
def find_err_detail(exc_detail):
if isinstance(exc_detail, ErrorDetail):
return exc_detail
if isinstance(exc_detail, dict):
keys = exc_detail.keys()
for key in keys:
_value = exc_detail[key]
if isinstance(_value, list):
return find_err_detail(_value)
if isinstance(_value, ErrorDetail):
return _value
if isinstance(_value, dict) and len(_value.keys()) > 0:
return find_err_detail(_value)
if isinstance(exc_detail, list):
for v in exc_detail:
r = find_err_detail(v)
if r is not None:
return r
def handle_exception(exc, context):
exception_class = exc.__class__
# 先调用REST framework默认的异常处理方法获得标准错误响应对象
response = exception_handler(exc, context)
# 在此处补充自定义的异常处理
if issubclass(exception_class, ValidationError):
return validation_error_to_result(exc)
if issubclass(exception_class, AppApiException):
return result.Result(exc.code, exc.message, response_status=exc.status_code)
if issubclass(exception_class, APIException):
return result.error(exc.detail)
if response is None:
maxkb_logger.error(f'{str(exc)}:{traceback.format_exc()}')
return result.error(str(exc))
return response