FastAPI教程-自定义业务异常

介绍

业务规则不满足,产生的错误,代码本身没有崩溃,程序可以正常继续运行,是业务逻辑层面的不符合预期。

例子

  • 用户账号密码错误
  • 余额不足,不能下单
  • 订单状态已取消,不能重复取消
  • 权限不足,禁止访问该数据
  • 手机号已经被注册
  • 商品库存为 0,无法购买

特点

  • 不是程序 bug,属于正常业务场景;
  • 服务没有崩溃,可以正常返回给前端提示;
  • HTTP 状态码一般仍然用 200 OK,在返回体内部用自定义code表示错误;
  • 不需要打印 ERROR 堆栈(大部分场景打 warn 即可)。

实现

继承 Exception,定义业务错误

例如业务码:

  • 10001 账号不存在
  • 10002 密码错误

自定义业务异常

class BusinessException(Exception):
    def __init__(self, code:int, msg:str):
        self.code = code
        self.msg = msg

注册处理器

捕获自定义业务异常

@app.exception_handler(BusinessException)
async def business_exception_handler(request: Request, exc: BusinessException):
    return JSONResponse(
        status_code=200, # 业务异常http码用200,靠内部code区分,前后端常用方案
        content={
            "code": exc.code,
            "msg": exc.msg,
            "data": None
        }
    )

实现视图函数

@app.get('/student/{name}')
async def get_student(name: str):
    if name == '李雷':
        ret = {
            "code": 200,
            "data": {
            'name': '李雷',
            'age': 21,
        }}
    else:
        raise BusinessException(code=10001, msg="没有此学号的学生")
    return ret

完整代码

from fastapi import FastAPI, Path
from fastapi.exceptions import RequestValidationError
from starlette.requests import Request
from starlette.responses import JSONResponse

app = FastAPI()

class BusinessException(Exception):
    def __init__(self, code:int, msg:str):
        self.code = code
        self.msg = msg


@app.exception_handler(BusinessException)
async def business_exception_handler(request: Request, exc: BusinessException):
    return JSONResponse(
        status_code=200, # 业务异常http码用200,靠内部code区分,前后端常用方案
        content={
            "code": exc.code,
            "msg": exc.msg,
            # "data": None
        }
    )


@app.get('/student/{name}')
async def get_student(name: str):
    if name == '李雷':
        ret = {
            "code": 200,
            "data": {
            'name': '李雷',
            'age': 21,
        }}
    else:
        raise BusinessException(code=10001, msg="没有此学号的学生")
    return ret

测试成功

浏览器访问:http://127.0.0.1:8000/student/李雷 ,浏览器显示:

{
    "code": 200,
    "data": {
        "name": "李雷",
        "age": 21
    }
}

测试找不到学生

浏览器访问:http://127.0.0.1:8000/student/lili ,浏览器显示:

{
    "code": 10001,
    "msg": "没有此学号的学生"
}

原文出处:/show_1GW3roi9Qtnb.html