第4节,FastAPI动态路由

FastAPI 提供动态路由的能力,在其官网上将其称之为路径参数,允许你使用与Python格式化字符串相同的语法来声明路径"参数"或"变量"。

1. 什么是动态路由

一个API接口需要返回用户的基本信息,比较传统的URL设计可能是下面的这样

/userinfo?uid=3

API接口的path 是 /userinfo ,url里的query部分是uid=3, 通过变化uid这个查询参数以获取不同用户的基本信息。

Restful 风格的API接口设计则是下面的样子

/userinfo/3

用户的uid 成为了接口url path里的一部分,想要获取uid 为4的用户的基本信息,请求的path为/userinfo/4, 在使用路由模块定义请求path与处理函数之间的映射关系时,你不可能根据uid穷举所有用户的path,这就要求路由模块必允许你定义一个可动态变化的url结构,这便是动态路由。

2. 动态路由示例

from fastapi import FastAPI


app = FastAPI()


@app.get('/userinfo/{uid}')
def user_info(uid):
    return {'msg': f"recv uid :{uid} type is {str(type(uid))}"}

启动服务后在浏览器里访问 http://127.0.0.1:8000/userinfo/5 ,得到的响应结果如下

{"msg":"recv uid :5 type is <class 'str'>"}

表示path的字符串 '/userinfo/{uid}' 采用了python格式化字符串时的语法,被{} 括起来的部分是允许发生变化的地方。

3. 有类型的路径参数

在上一小节的例子中,函数user_info的参数uid 实际传入的实参是字符串类型,这与uid通常为int类型的实践状态是不相符的,FastAPI允许你通过类型标注对路径参数进行转化

@app.get('/userinfo/{uid}')
def user_info(uid: int):
    return {'msg': f"recv uid :{uid} type is {str(type(uid))}"}

为参数uid 增加类型标注,将其标注为int类型,FastAPI将根据这个标注对uid进行类型转换,接口返回的内容变为

{"msg":"recv uid :5 type is <class 'int'>"}

uid被自动转为int类型,如此便不需要你自己再进行任何的转换,这正是FastAPI可以提高你工作效率的原因。

4. 数据校验

一旦你对路径参数进行了类型标注,如果在实际请求中传入了错误的参数,FastAPI可以帮你校验并返回错误,以第3小节的例子为基础,在浏览器里访问 http://127.0.0.1:8000/userinfo/string, string 不能转化为int类型数据,这是一次错误的请求,FastAPI返回的结果是

{
    "detail": [
        {
            "loc": [
                "path",
                "uid"
            ],
            "msg": "value is not a valid integer",
            "type": "type_error.integer"
        }
    ]
}

5. 定义顺序决定匹配顺序

现在新增一个API接口

@app.get('/userinfo/all')
def user_info_all():
    return {'msg': "all user info"}

@app.get('/userinfo/{uid}')
def user_info(uid: int):
    return {'msg': f"recv uid :{uid} type is {str(type(uid))}"}

路径 /userinfo/all 和 '/userinfo/{uid}' 是相似的,如果请求/userinfo/all 被user_info函数 处理了,all不能转为int类型数据,服务会报错。但实践中,这样写不会发生错误,,当请求/userinfo/all 到来时,user_info_all 和 user_info 都可以用来处理请求,但user_info_all定义在前,因此优先使用user_info_all 对请求进行处理。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案