Django后端相应类设计

embedded/2025/1/11 9:50:28/

通用的ApiResponse类:用于生成统一的 API 响应格式。每个响应都包含以下字段(每个接口最终的返回数据格式):

  • status_code:HTTP 状态码(如 200、400、500 等)
  • message:响应的描述信息(如 “Success”、“Resource not found” 等)
  • data:返回的数据(如果有)
  • trace_id:请求的唯一标识符

trace_id的作用:

  • 唯一标识请求:每个请求都有一个唯一的 TraceID
  • 日志关联:在日志中记录 TraceID,便于快速定位问题

ApiResponse类核心方法:
1、success 200 请求成功
2、created 201 创建资源成功
3、bad_request 400 后端必要的参数与前端传递的参数不一致。例如缺少必填字段、参数类型错误(如期望是数字,但传入了字符串)
4、unauthorized 401 用户鉴权问题,例如token失效,没有提供有效的身份验证信息
5、forbidden 403 禁止访问,客户端没有权限访问资源
6、not_found 404 请求的资源不存在,URL 路径错误。访问的 API 路径错误等
7、validation_error 422 请求格式正确,但语义错误,服务器无法处理。例如:邮箱格式不正确、密码长度不符合要求。请求数据不符合业务规则
8、conflict 409 资源冲突,请求与当前资源状态冲突.例如:创建资源时,资源已存在。用户重名等
9、internal_server_error 500 服务器内部错误,无法完成请求。例如:数据库连接失败,代码逻辑错误导致的异常
10、service_unavailable 503 服务不可用,服务器暂时无法处理请求。例如:服务器正在维护,第三方 API 服务失效等

中间件middlewares作用:
Django 中的一个全局异常处理器,它的主要作用是捕获 Django 视图函数或中间件中抛出的异常,并根据异常类型返回统一的错误响应
同时,它还支持 TraceID 的生成和传递,便于追踪请求的完整调用链路。

1、中间件会捕获所有未处理的异常(包括 Django 内置异常和自定义异常),根据异常类型,生成对应的错误响应
2、最终会使用 ApiResponse 类生成统一的错误响应格式(status_code、message、data、trace_id)
3、从请求头中获取 TraceID,如果未提供则自动生成一个新的。将异常信息和 TraceID 记录到日志中,便于后续排查问题

整体说明:
1、使用可参考test.py,接口最终返回的数据,需要经过结果处理类ApiResponse,统一进行处理
2、在视图(接口)中,尽量使用ApiResponse类的10个核心方法,捕捉可能发生的异常
3、中间件会捕捉,代码未处理的异常,最终规范为status_code、message、data、trace_id四个字段(中间键与ApiResponse结果处理类是互补的作用)
4、后端返回的数据,最终会规范为status_code、message、data、trace_id四个字段

python">class StatusCode:# 成功状态码SUCCESS = 200  # 请求成功CREATED = 201  # 创建资源成功# 客户端错误(4XX)BAD_REQUEST = 400  # 参数错误UNAUTHORIZED = 401  # 未授权FORBIDDEN = 403  # 禁止访问NOT_FOUND = 404  # 资源未找到VALIDATION_ERROR = 422  # 参数校验错误CONFLICT = 409  # 资源冲突# 服务端错误(5XX)SERVER_ERROR = 500  # 服务器内部错误SERVICE_UNAVAILABLE = 503  # 服务不可用class ApiException(Exception):"""基础异常类,所有自定义异常继承此类。"""def __init__(self, message, status_code):super().__init__(message)self.status_code = status_codeself.message = message# 客户端错误(4XX)
class BadRequestException(ApiException):"""400 Bad Request"""def __init__(self, message="Bad request"):super().__init__(message, status_code=StatusCode.BAD_REQUEST)class UnauthorizedException(ApiException):"""401 Unauthorized"""def __init__(self, message="Unauthorized"):super().__init__(message, status_code=StatusCode.UNAUTHORIZED)class ForbiddenException(ApiException):"""403 Forbidden"""def __init__(self, message="Forbidden"):super().__init__(message, status_code=StatusCode.FORBIDDEN)class NotFoundException(ApiException):"""404 Not Found"""def __init__(self, message="Resource not found"):super().__init__(message, status_code=StatusCode.NOT_FOUND)class ValidationErrorException(ApiException):"""422 Validation Error"""def __init__(self, message="Validation error"):super().__init__(message, status_code=StatusCode.VALIDATION_ERROR)class ConflictException(ApiException):"""409 Conflict"""def __init__(self, message="Conflict"):super().__init__(message, status_code=StatusCode.CONFLICT)# 服务端错误(5XX)
class InternalServerErrorException(ApiException):"""500 Internal Server Error"""def __init__(self, message="Internal server error"):super().__init__(message, status_code=StatusCode.SERVER_ERROR)class ServiceUnavailableException(ApiException):"""503 Service Unavailable"""def __init__(self, message="Service unavailable"):super().__init__(message, status_code=StatusCode.SERVICE_UNAVAILABLE)

以上为自定义的异常处理类,下述为自定义的中间件

python">import logging
import uuidfrom django.core.exceptions import PermissionDenied
from django.http import Http404from 响应类设计.exceptions import *
from 响应类设计.response_handler import ApiResponselogger = logging.getLogger(__name__)class ExceptionHandlingMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 从请求头中获取 Trace ID,如果没有则生成一个新的trace_id = request.headers.get('X-Trace-ID', str(uuid.uuid4()))request.trace_id = trace_id  # 将 Trace ID 绑定到请求对象try:response = self.get_response(request)return responseexcept Exception as e:return self.handle_exception(e, trace_id)def handle_exception(self, exception, trace_id):# 记录异常日志,包含 Trace IDlogger.error(f"Trace ID: {trace_id}, Error: {str(exception)}", exc_info=True)if isinstance(exception, Http404):return ApiResponse.not_found(message=str(exception), trace_id=trace_id)elif isinstance(exception, PermissionDenied):return ApiResponse.forbidden(message=str(exception), trace_id=trace_id)elif isinstance(exception, BadRequestException):return ApiResponse.bad_request(message=str(exception), trace_id=trace_id)elif isinstance(exception, UnauthorizedException):return ApiResponse.unauthorized(message=str(exception), trace_id=trace_id)elif isinstance(exception, ForbiddenException):return ApiResponse.forbidden(message=str(exception), trace_id=trace_id)elif isinstance(exception, NotFoundException):return ApiResponse.not_found(message=str(exception), trace_id=trace_id)elif isinstance(exception, ValidationErrorException):return ApiResponse.validation_error(message=str(exception), trace_id=trace_id)elif isinstance(exception, ConflictException):return ApiResponse.conflict(message=str(exception), trace_id=trace_id)elif isinstance(exception, InternalServerErrorException):return ApiResponse.internal_server_error(message=str(exception), trace_id=trace_id)elif isinstance(exception, ServiceUnavailableException):return ApiResponse.service_unavailable(message=str(exception), trace_id=trace_id)else:# 未知异常,返回 500 状态码return ApiResponse.internal_server_error(message="An unexpected error occurred.", trace_id=trace_id)
python">from django.http import JsonResponse
import uuidfrom 响应类设计.exceptions import StatusCodeclass ApiResponse:"""通用的 API 响应类,支持 Trace ID 和多种状态码。"""def __init__(self, status_code, message, data=None, trace_id=None):self.status_code = status_codeself.message = messageself.data = dataself.trace_id = trace_id or str(uuid.uuid4())  # 生成唯一的 Trace IDdef to_dict(self):"""将响应数据转换为字典格式。"""return {'status_code': self.status_code,'message': self.message,'data': self.data if self.data is not None else {},'trace_id': self.trace_id  # 包含 Trace ID}def to_json_response(self):"""将响应数据转换为 Django 的 JsonResponse。"""return JsonResponse(self.to_dict(), status=self.status_code)# 成功响应@staticmethoddef success(message="Success", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.SUCCESS, message=message, data=data,trace_id=trace_id).to_json_response()# 资源创建成功@staticmethoddef created(message="Resource created", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.CREATED, message=message, data=data,trace_id=trace_id).to_json_response()# 客户端错误@staticmethoddef bad_request(message="Bad request", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.BAD_REQUEST, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef unauthorized(message="Unauthorized", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.UNAUTHORIZED, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef forbidden(message="Forbidden", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.FORBIDDEN, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef not_found(message="Resource not found", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.NOT_FOUND, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef validation_error(message="Validation error", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.VALIDATION_ERROR, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef conflict(message="Conflict", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.CONFLICT, message=message, data=data,trace_id=trace_id).to_json_response()# 服务端错误@staticmethoddef internal_server_error(message="Internal server error", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.SERVER_ERROR, message=message, data=data,trace_id=trace_id).to_json_response()@staticmethoddef service_unavailable(message="Service unavailable", data=None, trace_id=None):return ApiResponse(status_code=StatusCode.SERVICE_UNAVAILABLE, message=message, data=data,trace_id=trace_id).to_json_response()

上述为定义的结果处理类,一下为使用说明案例

python">from django.views import View
import uuid
from .exceptions import BadRequestException, NotFoundException
from .response_handler import ApiResponsedef get_trace_id(request):"""从请求头中获取 Trace ID,如果没有则生成一个新的。"""return request.headers.get('X-Trace-ID', str(uuid.uuid4()))class MyView(View):def get(self, request, *args, **kwargs):"""示例 GET 请求视图,展示如何使用 Trace ID。"""# 获取或生成 Trace IDtrace_id = get_trace_id(request)# 示例:从 URL 参数中获取资源 IDresource_id = kwargs.get('resource_id')if not resource_id:# 如果资源 ID 不存在,返回 400 错误raise BadRequestException("Resource ID is required.")# 模拟资源查找resource = self.get_resource(resource_id)if not resource:# 如果资源未找到,返回 404 错误raise NotFoundException("Resource not found.")# 返回成功响应return ApiResponse.success(message="Resource retrieved successfully",data=resource,trace_id=trace_id)def post(self, request, *args, **kwargs):"""示例 POST 请求视图,展示如何使用 Trace ID。"""# 获取或生成 Trace IDtrace_id = get_trace_id(request)# 示例:从请求体中获取数据data = request.POSTif not data.get('name'):# 如果名称字段不存在,返回 400 错误raise BadRequestException("Name is required.")# 模拟创建资源resource = self.create_resource(data)return ApiResponse.created(message="Resource created successfully",data=resource,trace_id=trace_id)def get_resource(self, resource_id):"""模拟资源查找逻辑。"""# 这里可以替换为实际的数据库查询逻辑if resource_id == "123":return {"id": "123", "name": "Example Resource"}return Nonedef create_resource(self, data):"""模拟资源创建逻辑。"""# 这里可以替换为实际的数据库插入逻辑return {"id": str(uuid.uuid4()), "name": data.get('name')}

http://www.ppmy.cn/embedded/152973.html

相关文章

SQL SERVER__RSN 恢复的深入解析

1. RSN 的工作原理 RSN 是 SQL Server 内部用于跟踪和管理备份和恢复操作顺序的编号。每次数据库备份(包括完整备份、差异备份和事务日志备份)都会生成一个唯一的 RSN。SQL Server 在恢复过程中使用 RSN 来确保备份文件按正确的顺序应用,从而…

万字详解 MySQL MGR 高可用集群搭建

文章目录 1、MGR 前置介绍 1.1、什么是 MGR1.2、MGR 优点1.3、MGR 缺点1.4、MGR 适用场景 2、MySQL MGR 搭建流程 2.1、环境准备2.2、搭建流程 2.2.1、配置系统环境2.2.2、安装 MySQL2.2.3、配置启动 MySQL2.2.4、修改密码、设置主从同步2.2.5、安装 MGR 插件 3、MySQL MGR 故…

【机器学习篇】探索机器学习在农业中的应用:从作物预测到精准农业

准备开启这场美妙的旅行吧!!! 目录 一机器学习在农业中的重要性: 1.1提高产量和质量: 1.2资源优化配置: 1.3病虫害防治: 二作物产量预测及回归分析: 2.1理论基础&#xff1a…

Scala语言的面向对象编程

Scala语言的面向对象编程 面向对象编程(Object-Oriented Programming,OOP)是一种编程范式,它使用“对象”来组织代码,这些对象能够包含数据(属性)以及功能(方法)。Scala…

120.Jenkins里的Pipeline Script

目录 1. **Declarative Pipeline** 主要部分 示例 2. **Scripted Pipeline** 主要部分 示例 3. **常用指令和功能** 环境变量 工具管理 文件操作 构建触发器 并行执行 异常处理 用户交互 4.**两种类型的特点** 1. **声明式 Pipeline (Declarative Pipeline)** 中…

【前端】【HTML】入门基础知识

参考视频&#xff1a;【狂神说Java】HTML5完整教学通俗易懂_哔哩哔哩_bilibili 一、基本结构 二、基本标签 <h1>&#xff1a;一级标题&#xff0c;通常用于页面的主标题&#xff0c;字体较大且醒目。 <h2>&#xff1a;二级标题&#xff0c;用于副标题或主要章节标…

1. npm 常用命令详解

npm 常用命令详解 npm&#xff08;Node Package Manager&#xff09;是 Node.js 的包管理工具&#xff0c;用于安装和管理 Node.js 应用中的依赖库。下面是 npm 的一些常用命令及其详细解释和示例代码。 镜像源 # 查询当前使用的镜像源 npm get registry# 设置为淘宝镜像源 …

Java一个简单的反弹动画练习

文章目录 说明代码详解创建窗体代码创建绘图板创建线程 运行结果完整代码 说明 做了一个小球和星型做反弹动画的窗体作为练习&#xff0c;分享给大家&#xff0c;为了方便和我一样的小白可以看的比较明白&#xff0c;所以尽量详细的标注了注释&#xff0c;希望能帮到同样在学习…