路径参数定义
路径参数是 URL
中的一部分,用于捕获动态值。例如,在一个博客应用中,你可能希望通过 URL 来获取特定文章的详细信息。URL 可能看起来像这样:/articles/123,其中 123 是文章的 ID。在这个例子中,123 就是一个路径参数。
FastAPI 允许你通过定义路径操作函数(Path Operation Function)来捕获这些动态值,并将它们作为参数传递给函数
基本用法
from fastapi import FastAPI
app = FastAPI()
@app.get("/users/{user_id}")
async def read_user(user_id: int):
return {"user_id": user_id}
代码解析
- 定义路径操作函数:我们使用
@app.get("/users/{user_id}")
装饰器来定义一个 GET 请求的路径操作函数。{user_id}
是路径参数,FastAPI 会自动将其捕获并传递给函数 - 函数参数:
read_user
函数的参数user_id
被声明为int
类型。FastAPI 会自动将 URL 中的user_id
转换为整数类型,并进行数据验证。如果user_id
不是整数,FastAPI 会返回一个 422 错误(Unprocessable Entity) - 返回结果:函数返回一个包含 user_id 的字典
测试 API
启动 FastAPI 应用后,你可以通过访问 /users/123 来测试这个 API。FastAPI 会自动将 123 转换为整数,并返回 {"user_id": 123}
路径参数的类型转换
FastAPI 支持多种类型的路径参数,包括 int
、float
、str
、bool
等。你可以根据需要选择合适的类型
示例:使用 str 类型的路径参数
@app.get("/items/{item_name}")
async def read_item(item_name: str):
return {"item_name": item_name}
在这个例子中,item_name 是一个字符串类型的路径参数。你可以访问 /items/foo
,FastAPI 会返回 {"item_name": "foo"}
示例:使用 float 类型的路径参数
@app.get("/prices/{price}")
async def read_price(price: float):
return {"price": price}
在这个例子中,price 是一个浮点数类型的路径参数。你可以访问 /prices/19.99
,FastAPI 会返回 {"price": 19.99}
路径参数的顺序
在 FastAPI 中,路径参数的顺序非常重要。如果你定义了多个路径参数,它们的顺序必须与 URL 中的顺序一致
示例:多个路径参数
@app.get("/users/{user_id}/items/{item_id}")
async def read_user_item(user_id: int, item_id: int):
return {"user_id": user_id, "item_id": item_id}
在这个例子中,我们定义了两个路径参数:user_id 和 item_id。你可以访问 /users/123/items/456
,FastAPI 会返回 {"user_id": 123, "item_id": 456}
路径参数与查询参数的区别
路径参数是 URL 的一部分,而查询参数是 URL 中 ?
后面的部分。例如,在 /users/123?name=John
中,123
是路径参数,name=John
是查询参数
示例:路径参数与查询参数结合使用
@app.get("/users/{user_id}")
async def read_user(user_id: int, name: str = None):
return {"user_id": user_id, "name": name}
在这个例子中,user_id
是路径参数,name
是查询参数。你可以访问/users/123?name=John
,FastAPI 会返回 {"user_id": 123, "name": "John"}
路径参数的验证
通常,我们会直接使用 name:str='phyger'
的方式来限定路径参数的类型和默认值,但是对于路径参数的高级元数据,我们需要借助 FastApi 为我们提供的 Path 对象来实现。
路径参数的 title
from fastapi import Path
@app.get('/path/{name}')
async def pth(name:str=Path(...,title='path name')):
return {'path_name':name}
限定路径参数的格式
数值校验
大于2:gt=2
小于2:lt=2
大于等于2:ge=2
小于等于2:le=2
from fastapi import Path
@app.get('/path/{name}')
async def pth(* ,name:int=Path(...,title='path name',ge=2),q:str):
return {'path_name':name}
jopa@jopa-PC:~$ curl 'http://127.0.0.1:8000/path/1?q=q'
{"detail":[{"type":"greater_than_equal","loc":["path","name"],"msg":"Input should be greater than or equal to 2","input":"1","ctx":{"ge":2}}]}
jopa@jopaurl 'http://127.0.0.1:8000/path/3?q=q'
{"path_name":3}
路径参数的顺序问题
当我们的业务模型中有两个 uri,一个路径参数是固定值,另一个是路径参数是变量,该如何处理呢?
假设当前业务中的视图有如下两条:
@app.get('/path/{name}')
async def pth(name:str=Path(...,title='path name')):
return {'path_name':name}
@app.get('/path/default')
async def f1():
return {'msg':'I am default path.'}
分析以上代码,当我们请求/path/default的时候,我们会得到{'msg':'I am default path.'}的结果。
测试一下:
jopa@jopa-PC:~$ curl "http://127.0.0.1:8000/path/default"
{"path_name":"default"}
这是怎么回事?和我预期的不一致
url
冲突了,对于/path/default
而言,/path/{name}已经拦截了所有符合/path/xxx的请求。我们只要将他两的顺序调整为固前变后(固定路径参数在前,变化路径参数在后)即可
修改的代码
@app.get('/path/default')
async def f1():
return {'msg':'I am default path.'}
@app.get('/path/{name}')
async def pth(name:str=Path(...,title='path name')):
return {'path_name':name}
再次测试:
jopa@jopa-PC:~$ curl "http://127.0.0.1:8000/path/default"
{"msg":"I am default path."}
可以看到,/path/default
已经成功拦截并返回正确的结果
再测试下非固定参数的功能
jopa@jopa-PC:~$ curl "http://127.0.0.1:8000/path/phyger"
{"path_name":"phyger"}
可以看到,我们的非固定路径参数的其他功能均正常
常用路径操作装饰器方法参数详解
1. response_model:定义响应数据模型
response_model
参数用于指定接口返回的数据模型,FastAPI
会自动将返回的数据转换为该模型定义的格式,并进行数据验证和序列化。这不仅能规范接口输出,还能在 API 文档(如 Swagger UI
和 ReDoc)中自动生成清晰的响应结构说明。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/items/{item_id}", response_model=Item)
async def read_item(item_id: int):
return {"name": "Sample Item", "price": 19.99}
在上述示例中,response_model=Item
表示接口返回的数据将按照 Item
模型的结构进行校验和输出。如果返回的数据不符合 Item
模型的定义,FastAPI 会自动返回错误响应
2. status_code:设置响应状态码
status_code
参数允许你自定义接口响应的 HTTP 状态码。默认情况下,不同的操作类型有对应的默认状态码(如 GET 请求默认 200,POST 请求默认 201),但通过 status_code 可以根据实际业务需求进行修改
from fastapi import FastAPI
app = FastAPI()
@app.post("/items/", status_code=201)
async def create_item():
return {"message": "Item created"}
在这个例子中,创建资源的 POST 接口将返回状态码 201(表示资源已创建),明确告知客户端操作结果
3. summary 和 description:接口文档说明
summary
和 description
参数用于在 API 文档中添加接口的简要说明和详细描述,帮助开发者更好地理解接口功能和使用方法
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", summary="获取项目列表", description="该接口用于获取所有项目的详细信息")
async def read_items():
return [{"name": "Item 1"}, {"name": "Item 2"}]
通过设置这两个参数,在 Swagger UI
和 ReDoc
中展示的 API
文档会更加清晰易懂,方便团队协作和接口维护
4. tags:接口分组归类
tags
参数可以将相关的接口进行分组,在 API 文档中以标签的形式展示,便于管理和查找
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", tags=["items"])
async def read_items():
return [{"name": "Item 1"}, {"name": "Item 2"}]
@app.get("/users/", tags=["users"])
async def read_users():
return [{"name": "User 1"}, {"name": "User 2"}]
在 API 文档中,带有相同 tags 的接口会被归为一组,方便开发者快速定位特定功能的接口
5. dependencies:添加依赖项
dependencies
参数用于指定接口所需的依赖项,这些依赖项可以是函数、类或其他可调用对象。FastAPI 会在处理请求前解析并执行这些依赖项,常用于权限验证、数据预处理等场景
from fastapi import Depends, FastAPI
app = FastAPI()
def common_parameters(q: str = None, skip: int = 0, limit: int = 10):
return {"q": q, "skip": skip, "limit": limit}
@app.get("/items/", dependencies=[Depends(common_parameters)])
async def read_items(commons: dict = Depends(common_parameters)):
return commons
在上述代码中,dependencies=[Depends(common_parameters)]
表示 read_items
接口依赖于 common_parameters
函数,该函数会处理请求中的查询参数,并将结果传递给接口函数
6. responses:自定义响应描述
responses
参数用于更详细地定义接口的各种响应情况,除了默认的成功响应外,还可以说明错误响应的状态码、内容和含义
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}", responses={
404: {"description": "Item not found"},
500: {"description": "Internal server error"}
})
async def read_item(item_id: int):
# 假设此处存在获取item的逻辑,如果未找到则可能返回404
pass
通过 responses
参数,在 API 文档中可以清晰展示接口可能出现的各种响应情况,让调用者提前了解错误处理机制
7. deprecated: 标记接口为弃用状态
deprecated
参数用于标记某个接口已被弃用,提醒开发者该接口将在未来版本中移除,建议使用替代接口。在 API 文档中,被标记为弃用的接口会显示特殊的视觉提示,帮助调用者避免使用过时的接口
from fastapi import FastAPI
app = FastAPI()
@app.get("/old-endpoint/", deprecated=True)
async def old_endpoint():
return {"message": "This endpoint is deprecated, please use /new-endpoint/ instead"}
@app.get("/new-endpoint/")
async def new_endpoint():
return {"message": "This is the new and improved endpoint"}
在 Swagger UI
中,弃用的接口会显示一条删除线和警告标识,清晰地告知用户该接口已不再推荐使用。这对于 API 版本迭代和接口迁移非常有用,可以平滑过渡用户使用习惯,减少兼容性问题
总结
FastAPI 的路径参数功能非常强大且灵活。通过路径参数,你可以轻松构建动态 URL,并捕获 URL 中的动态值。FastAPI 还提供了丰富的类型支持和数据验证功能,帮助你构建健壮的 API。
在实际开发中,路径参数是构建 RESTful API 的重要组成部分。掌握路径参数的使用方法,可以帮助你更好地设计和实现 API