Django后端相应类设计

通用的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四个字段

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)

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

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)
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()

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

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.mzph.cn/web/65782.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2)

汽车基础软件AutoSAR自学攻略(三)-AutoSAR CP分层架构(2) 下面我们继续来介绍AutoSAR CP分层架构,下面的文字和图来自AutoSAR官网目前最新的标准R24-11的分层架构手册。该手册详细讲解了AutoSAR分层架构的设计,下面让我们来一起学习一下。 Introductio…

css面试常考布局(圣杯布局、双飞翼布局、三栏布局、两栏布局、三角形)

两栏布局 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title> </head> &…

网络攻击行为可视化分析系统【数据分析 + 可视化】

一、系统背景 随着信息技术的快速发展&#xff0c;网络已成为现代社会不可或缺的一部分。然而&#xff0c;与此同时&#xff0c;网络攻击手段也日益多样化和复杂化&#xff0c;给企业和个人的信息安全带来了极大的威胁。传统的网络攻击分析方法往往依赖于人工分析和处理大量的…

利用obs studio制作(人像+屏幕)录制影像

1.什么是obs? OBS&#xff08;Open Broadcaster Software&#xff09;是一款功能强大的开源软件&#xff0c;它使用户能够直接从电脑录制视频和直播内容到 Twitch&#xff0c;YouTube 和 Facebook Live 等平台。它在需要直播或录制屏幕活动的游戏玩家、YouTube 用户和专业人士…

C# GDI+的DrawString无法绘制Tab键的现象

【啰嗦2句】 现在用C#的人很少了吧&#xff1f;GDI更少了吧&#xff1f;所以这个问题估计也冷门。没关系&#xff0c;分享给特定需要的人也不错。 【问题现象】 工作中开发了一个报告编辑器&#xff0c;实现图文排版等功能&#xff0c;用着没什么问题&#xff0c;直到有一天…

夯实前端基础之HTML篇

知识点概览 HTML部分 1. DOM和BOM有什么区别&#xff1f; DOM&#xff08;Document Object Model&#xff09; 当网页被加载时&#xff0c;浏览器会创建页面的对象文档模型&#xff0c;HTML DOM 模型被结构化为对象树 用途&#xff1a; 主要用于网页内容的动态修改和交互&…

SD ComfyUI工作流 老照片修复上色

文章目录 老照片修复上色SD模型Node节点工作流程开发与应用效果展示老照片修复上色 该工作流专门设计用于老照片的修复和上色,通过一系列高级的图像处理技术,包括深度图预处理、面部修复、上色和图像放大等步骤,来恢复老照片的质量并增加色彩。首先,工作流加载老照片并进行…

后端技术选型 sa-token校验学习 下 结合项目学习 前后端登录

目录 后端设置 Controller 层 Service 层 后端返回 Token 给前端 1. 用户提交登录请求 2. 后端验证用户身份 3. 返回 Token 4. 前端保存 Token 前端存储 1. 前端向后端发起请求 2. 前端存储一下 Token 3.管理用户认证的 token 的 工具 4. 在 Service 层进行设置 H…

如何用 SSH 访问 QNX 虚拟机

QNX 虚拟机默认是开启 SSH 服务的&#xff0c;如果要用 SSH 访问 QNX 虚拟机&#xff0c;就需要知道虚拟机的 IP 地址&#xff0c;用户和密码。本文我们来看看如何获取这些参数。 1. 启动虚拟机 启动过程很慢&#xff0c;请耐心等待。 2. 查看 IP 地址 等待 IDE 连接到虚拟机。…

java面向对象编程特性概述

目录 1. 类和对象 2. 封装&#xff08;Encapsulation&#xff09; 3. 继承&#xff08;Inheritance&#xff09; 4. 多态&#xff08;Polymorphism&#xff09; 5. 抽象&#xff08;Abstraction&#xff09; (1). 抽象类&#xff08;Abstract Class&#xff09; (2).接口…

React(二)——Admin主页/Orders页面/Category页面

文章目录 项目地址一、侧边栏1.1 具体实现 二、Header2.1 实现 三、Orders页面3.1 分页和搜索3.2 点击箭头显示商家所有订单3.3 页码按钮以及分页 四、Category页面4.1 左侧商品添加栏目4.2 右侧商品上传栏 五、Sellers页面六、Payment Request 页面&#xff08;百万数据加载&a…

maven 下载依赖 jhash:2.1.2 和对应 jar 包

原文地址 前言 25年新的一年&#xff0c;那就先更新一篇技术文章吧&#xff0c;这个是这几天刚遇到的一个有意思的bug&#xff0c;记录分享一下 原因分析 在使用maven加载一个项目的时&#xff0c;发现maven的依赖一直无法解析&#xff0c;更换阿里云镜像和中央仓库都没办法…

nums[:]数组切片

问题&#xff1a;给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 使用代码如下没有办法通过测试示例&#xff0c;必须将最后一行代码改成 nums[:]nums[-k:]nums[:-k]切片形式&#xff1a; 原因&#xff1a;列表的切片操作 …

python-leetcode-三数之和

15. 三数之和 - 力扣&#xff08;LeetCode&#xff09; class Solution:def threeSum(self, nums: List[int]) -> List[List[int]]:nums.sort() # 排序n len(nums)res []for i in range(n):# 剪枝&#xff1a;如果当前数 > 0&#xff0c;三数之和不可能为 0if nums[i]…

极狐GitLab 正式发布安全版本17.7.1、17.6.3、17.5.5

本分分享极狐GitLab 补丁版本 17.7.1, 17.6.3, 17.5.5 的详细内容。这几个版本包含重要的缺陷和安全修复代码&#xff0c;我们强烈建议所有私有化部署用户应该立即升级到上述的某一个版本。对于极狐GitLab SaaS&#xff0c;技术团队已经进行了升级&#xff0c;无需用户采取任何…

探索绿色能源系统的固态继电器:2025年展望

随着全球向绿色能源转型的加速&#xff0c;对高效、可靠和环保元件的需求从未如此强烈。在这种背景下&#xff0c;国产固态继电器(SSR)在实现太阳能逆变器、风力涡轮机和储能系统等关键技术方面发挥着关键作用。本文探讨了绿色能源系统背景下中国固态继电器行业的前景&#xff…

Rust语言使用iced实现简单GUI页面

使用cargo新建一个rust项目 cargo new gui_demo cd gui_demo 编辑Cargo.toml文件 ,添加iced依赖 [package] name "gui_demo" version "0.1.0" edition "2021"[dependencies] iced "0.4.2" 编辑src/main.rs文件&#xff1a; u…

Github提交Pull Request教程 Git基础扫盲(零基础易懂)

1 PR是什么&#xff1f; PR&#xff0c;全称Pull Request&#xff08;拉取请求&#xff09;&#xff0c;是一种非常重要的协作机制&#xff0c;它是 Git 和 GitHub 等代码托管平台中常见的功能&#xff0c;被广泛用于参与社区贡献&#xff0c;从而促进项目的发展。 PR的整个过…

RabbitMQ 可观测性最佳实践

RabbitMQ 简介 RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写&#xff0c;支持多种客户端。它通过使用交换机&#xff08;Exchanges&#xff09;、队列&#xff08;Queues&#xff09;和绑定&#xff08;Bindings&#xff09;来路由消息&#xff…

美摄科技PC端视频编辑解决方案,为企业打造专属的高效创作平台

在当今这个信息爆炸的时代&#xff0c;视频已成为不可或缺的重要内容形式&#xff0c;美摄科技推出了PC端视频编辑解决方案的私有化部署服务&#xff0c;旨在为企业提供一款量身定制的高效创作平台。 一、全面功能&#xff0c;满足企业多样化需求 美摄科技的PC端视频编辑解决…