FastAPI教程-路由获取参数

二、路径参数(路径变量)

URL路径里的变量,用{变量名},函数参数接收。FastAPI自动做类型校验。

# 路径参数
@app.get("/items/{item_id}")
def read_item(item_id: int): # 自动转int,非数字直接返回422校验错误
    return {"item_id": item_id}

路径参数优先级规则

静态路径 > 变量路径,顺序从上到下匹配,先定义先匹配

@app.get("/items/me")   # 静态路径,优先匹配
def read_me():
    return {"me": True}

@app.get("/items/{item_id}")
def read_item(item_id:int):
    return {"id":item_id}

⚠️ 如果把/{item_id}写在/me前面,访问/items/me会把me赋值给item_id,报int转换异常。

路径参数带枚举限制

from enum import Enum

class ModelName(str, Enum):
    alexnet = "alexnet"
    resnet = "resnet"

@app.get("/models/{model_name}")
def get_model(model_name: ModelName):
    return {"model": model_name}

路径包含路径(path类型,匹配/)

/files/{file_path:path}可以匹配带斜杠的路径,例如/files/a/b/c.txt

@app.get("/files/{file_path:path}")
def read_file(file_path: str):
    return {"file_path": file_path}

三、查询参数(Query参数,url?key=value)

不在路径中,在?后面,函数普通参数就是查询参数。

@app.get("/items/")
def read_items(skip: int = 0, limit: int | None = None):
    return {"skip": skip, "limit": limit}
  • 带默认值:skip:int=0,不传使用默认
  • limit: int | None = None:可选参数,可以不传

Query高级校验

from fastapi import Query

@app.get("/products")
def qry(
    page: int = Query(1, ge=1, description="页码>=1"),
    keyword: str | None = Query(None, min_length=2, max_length=20)
):
    return locals()

四、路由元信息(装饰器参数)

@app.get(
    "/items/{item_id}",
    summary="获取单个商品",
    description="根据id获取商品详情",
    tags=["商品管理"], # openapi文档分组
    response_description="返回商品json",
    deprecated=False, # 是否标记接口废弃
    status_code=200,  # 默认响应状态码
)
def get_item(item_id:int):
    return {"id":item_id}

五、APIRouter 模块化路由(大型项目必用)

把路由拆分到不同文件,实现接口模块化,统一加前缀、tags。

items.py

from fastapi import APIRouter

router = APIRouter(
    prefix="/items", # 该组所有路由自动拼接前缀
    tags=["商品模块"]
)

@router.get("/")
def list_items():
    return {"data":"商品列表"}

@router.get("/{item_id}")
def get_one(item_id:int):
    return {"id":item_id}

main.py

from fastapi import FastAPI
from items import router as item_router

app = FastAPI()
# 注册子路由
app.include_router(item_router)

APIRouter 参数说明

  • prefix:统一路径前缀,不要末尾写/
  • tags:分组标签
  • dependencies:该路由组全部接口共用依赖
  • responses:统一预设错误响应

还可以嵌套路由:include_router可以多次嵌套。

六、路由的依赖 dependencies

单接口依赖

from fastapi import Depends

def get_token():
    return "abc123"

@app.get("/secret", dependencies=[Depends(get_token)])
def secret():
    return {"ok":True}

APIRouter全局依赖,组内全部接口生效

router = APIRouter(
    prefix="/admin",
    dependencies=[Depends(check_admin)]
)

app全局依赖(所有接口)

app = FastAPI(dependencies=[Depends(global_auth)])

七、路由响应配置

  1. response_model:过滤输出字段,Pydantic模型
  2. status_code:返回状态码
  3. responses:额外文档的错误码示例
    ```python
    from pydantic import BaseModel

class ItemOut(BaseModel):
id:int
name:str

@app.get(“/item/{id}”, response_model=ItemOut, status_code=200, responses={404:{“description”:”找不到”}})
def get_item(id:int):
return {“id”:id,”name”:”xxx”,”secret”:”不会返回”}


## 八、路由匹配原理
1. 请求进来,starlette遍历注册的路由列表,从上往下匹配;
2. 优先完全静态匹配,再匹配路径参数;
3. 匹配成功执行对应函数;
4. 函数参数解析来源:路径参数、query、body、header、cookie、依赖;
5. pydantic校验参数,校验失败返回422;
6. 返回值自动json序列化。

> ⚠️重要:**路由定义顺序很关键,静态路由写在变量路由前面,否则会被变量路由拦截**。

## 九、特殊路由
### 1. 重定向 RedirectResponse
```python
from fastapi.responses import RedirectResponse
@app.get("/go")
def go():
    return RedirectResponse("/docs")

2. 文件响应 FileResponse

from fastapi.responses import FileResponse
@app.get("/download")
def download():
    return FileResponse("test.txt")

3. 挂载子应用(mount)

把另外一个starlette/fastapi应用挂载到某个路径下,不是路由,是完整子应用。

from fastapi import FastAPI

sub_app = FastAPI()
@sub_app.get("/hello")
def h():return {"hi":"sub"}

app = FastAPI()
app.mount("/sub", sub_app)
# 访问 /sub/hello

mount 和 include_router区别:

  • include_router:只是把路由规则合并到主app,共享文档;
  • mount:挂载完整独立应用,openapi文档不会合并。

十、常用路由调试工具

访问自动文档:

  • SwaggerUI:/docs
  • ReDoc:/redoc

完整项目目录示例(模块化)

main.py
routers/
    __init__.py
    user.py
    goods.py

main.py

from fastapi import FastAPI
from routers.user import router as user_router
from routers.goods import router as goods_router

app = FastAPI(title="路由演示")
app.include_router(user_router)
app.include_router(goods_router)

routers/user.py

from fastapi import APIRouter
router = APIRouter(prefix="/user", tags=["用户"])

@router.get("/list")
def user_list():
    return {"users":[]}

常见坑总结

  1. 路由顺序错误,静态接口被路径参数接口拦截;
  2. prefix="/items/"末尾多斜杠,导致拼接双斜杠;推荐prefix="/items";
  3. 路径参数类型写错,请求直接422;
  4. mount和include_router混淆,子应用看不到文档;
  5. POST接口,把参数写为普通函数参数,误当成query参数(body参数需要pydantic模型)。

如果你需要,我可以给你一份可直接运行完整示例代码,或者讲路由内部源码解析。


原文出处:/show_1GW3ooojxtbd.html