mirror of
https://github.com/huge-dream/django-vue3-admin.git
synced 2026-09-26 14:23:46 +00:00
116 lines
3.7 KiB
Python
116 lines
3.7 KiB
Python
# -*- coding: utf-8 -*-
|
||
|
||
"""
|
||
@author: 猿小天
|
||
@contact: QQ:1638245306
|
||
@Created on: 2021/6/2 002 16:06
|
||
@Remark: 自定义异常处理
|
||
"""
|
||
import logging
|
||
import traceback
|
||
|
||
from django.db.models import ProtectedError
|
||
from django.http import Http404
|
||
from rest_framework.exceptions import APIException as DRFAPIException, AuthenticationFailed, NotAuthenticated
|
||
from rest_framework.status import HTTP_401_UNAUTHORIZED
|
||
from rest_framework.views import set_rollback, exception_handler
|
||
|
||
from dvadmin.utils.json_response import ErrorResponse
|
||
|
||
logger = logging.getLogger(__name__)
|
||
|
||
|
||
def _format_drf_detail(detail):
|
||
"""
|
||
将 DRF ValidationError.detail 转为可读字符串。
|
||
避免嵌套列表(如 items 多行明细)在简单拼接时只剩「items:{}」等无效提示。
|
||
"""
|
||
if detail is None:
|
||
return ""
|
||
if isinstance(detail, dict):
|
||
if not detail:
|
||
return ""
|
||
parts = []
|
||
for k, v in detail.items():
|
||
if isinstance(v, (list, tuple)):
|
||
subs = []
|
||
for item in v:
|
||
if isinstance(item, dict):
|
||
inner = _format_drf_detail(item)
|
||
if inner:
|
||
subs.append(inner)
|
||
else:
|
||
subs.append(str(item))
|
||
if subs:
|
||
parts.append("%s: %s" % (k, ";".join(subs)))
|
||
elif isinstance(v, dict):
|
||
inner = _format_drf_detail(v)
|
||
if inner:
|
||
parts.append("%s: %s" % (k, inner))
|
||
else:
|
||
parts.append("%s: %s" % (k, v))
|
||
return ";".join(parts)
|
||
if isinstance(detail, (list, tuple)):
|
||
subs = []
|
||
for item in detail:
|
||
if isinstance(item, dict):
|
||
inner = _format_drf_detail(item)
|
||
if inner:
|
||
subs.append(inner)
|
||
else:
|
||
subs.append(str(item))
|
||
return ";".join(subs)
|
||
return str(detail)
|
||
|
||
|
||
class CustomAuthenticationFailed(NotAuthenticated):
|
||
# 设置 status_code 属性为 400
|
||
status_code = 400
|
||
|
||
def CustomExceptionHandler(ex, context):
|
||
"""
|
||
统一异常拦截处理
|
||
目的:(1)取消所有的500异常响应,统一响应为标准错误返回
|
||
(2)准确显示错误信息
|
||
:param ex:
|
||
:param context:
|
||
:return:
|
||
"""
|
||
msg = ''
|
||
code = 4000
|
||
# 调用默认的异常处理函数
|
||
response = exception_handler(ex, context)
|
||
if isinstance(ex, AuthenticationFailed):
|
||
# 如果是身份验证错误
|
||
if response and response.data.get('detail') == "Given token not valid for any token type":
|
||
code = 401
|
||
msg = ex.detail
|
||
elif response and response.data.get('detail') == "Token is blacklisted":
|
||
# token在黑名单
|
||
return ErrorResponse(status=HTTP_401_UNAUTHORIZED)
|
||
else:
|
||
code = 401
|
||
msg = ex.detail
|
||
elif isinstance(ex,Http404):
|
||
code = 400
|
||
msg = "接口地址不正确"
|
||
elif isinstance(ex, DRFAPIException):
|
||
set_rollback()
|
||
detail = ex.detail
|
||
if isinstance(detail, dict):
|
||
msg = _format_drf_detail(detail) or str(detail)
|
||
elif isinstance(detail, (list, tuple)):
|
||
msg = _format_drf_detail(detail) or str(detail)
|
||
else:
|
||
msg = str(detail)
|
||
elif isinstance(ex, ProtectedError):
|
||
set_rollback()
|
||
msg = "删除失败:该条数据与其他数据有相关绑定"
|
||
# elif isinstance(ex, DatabaseError):
|
||
# set_rollback()
|
||
# msg = "接口服务器异常,请联系管理员"
|
||
elif isinstance(ex, Exception):
|
||
logger.exception(traceback.format_exc())
|
||
msg = str(ex)
|
||
return ErrorResponse(msg=msg, code=code)
|