路径参数定义

路径参数是 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 支持多种类型的路径参数,包括 intfloatstrbool 等。你可以根据需要选择合适的类型

示例:使用 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:接口文档说明

summarydescription 参数用于在 API 文档中添加接口的简要说明和详细描述,帮助开发者更好地理解接口功能和使用方法

from fastapi import FastAPI

app = FastAPI()

@app.get("/items/", summary="获取项目列表", description="该接口用于获取所有项目的详细信息")
async def read_items():
    return [{"name": "Item 1"}, {"name": "Item 2"}]

通过设置这两个参数,在 Swagger UIReDoc 中展示的 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

最后修改:2025 年 06 月 03 日
如果觉得我的文章对你有用,请随意赞赏