| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- # coding=utf-8
- """
- @project: qabot
- @Author:虎
- @file: handle_exception.py
- @date:2023/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
|