import logging from rest_framework.views import exception_handler as drf_exception_handler logger = logging.getLogger(__name__) def _error_messages(details): messages = [] def collect(value): if isinstance(value, dict): for item in value.values(): collect(item) elif isinstance(value, (list, tuple)): for item in value: collect(item) elif value is not None: message = str(value).strip() if message and message not in messages: messages.append(message) collect(details) return messages def _error_message(details): messages = _error_messages(details) if not messages: return "请求未能完成" return ";".join(messages)[:300] def exception_handler(exc, context): response = drf_exception_handler(exc, context) request = context.get("request") if response is None: logger.exception( "api_unhandled_error method=%s path=%s", getattr(request, "method", "-"), getattr(request, "path", "-"), ) return response details = response.data code = getattr(exc, "default_code", "request_error") message = _error_message(details) fields = ",".join(details.keys()) if isinstance(details, dict) else "-" logger.info( "api_request_error method=%s path=%s status=%s code=%s fields=%s message=%s", getattr(request, "method", "-"), getattr(request, "path", "-"), response.status_code, code, fields, message, ) response.data = { "error": { "code": code, "message": message, "details": details, "request_id": getattr(request, "request_id", None), } } return response