fastApi-基础路由
FastAPI 基础路由 全套核心重点(零基础吃透,面试+写接口必掌握)
一、路由是什么
路由 = URL地址 + 请求方式 + 绑定执行函数
用户访问某个地址、提交数据,框架根据路由找到对应的Python函数执行,最后返回结果。
FastAPI 底层基于 Starlette,路由匹配自上而下依次匹配,匹配到第一个符合条件的路由就终止。
二、五大请求方式(最常用)
@app.get("/path") # 查询数据,浏览器直接访问、获取列表/详情,无请求体
@app.post("/path") # 提交数据:登录、提问、创建内容、LLM对话 90%用POST
@app.put("/path") # 全量更新整条数据
@app.patch("/path") # 局部更新部分字段
@app.delete("/path") # 删除数据
使用场景区分
- GET:只读取数据、不修改服务器内容,参数拼在url里,不能传递复杂JSON
- POST:提交复杂数据(大段文本、对话参数、嵌套json),RAG问答接口一律POST
三、三大参数传递形式(路由核心重难点)
1. 路径参数(URL路径里动态值)
格式:/xxx/{变量名}
特点:
- 写在url路径中;
- 可以指定类型,FastAPI自动类型校验;
- 必须传,不可省略。
from fastapi import FastAPI
app = FastAPI()
# 路径参数 user_id,强制int类型
@app.get("/user/{user_id}")
def get_user(user_id: int):
return {"用户ID": user_id, "类型": type(user_id)}
访问:http://127.0.0.1:8000/user/100
传入字符串如 /user/abc 会直接报错:类型不合法。
多级路径参数、多个路径参数
@app.get("/article/{article_id}/comment/{comment_id}")
def get_comment(article_id: int, comment_id: int):
return {"文章": article_id, "评论": comment_id}
路由匹配优先级:静态路由 > 动态路径路由
# 静态固定路由(优先匹配)
@app.get("/user/me")
def myself():
return {"info": "当前登录用户"}
# 动态路由(放在下面)
@app.get("/user/{user_id}")
def get_user(user_id: int):
return {"id": user_id}
重点规则:固定地址路由一定要写在动态变量路由上方,否则会被动态路由拦截。
2. 查询参数(Query参数:url ?key=value)
格式:/chat?prompt=什么是向量&temperature=0.7
特点:
- 问号后面拼接键值对;
- 适合简短参数;
- 可以设置默认值、可选参数;
- 自动类型转换+校验。
# prompt必填,temperature有默认值0.7
@app.get("/chat")
def chat(prompt: str, temperature: float = 0.7):
return {"提问": prompt, "温度参数": temperature}
可选参数:使用 Optional
from typing import Optional
@app.get("/search")
def search(keyword: str, page: Optional[int] = None):
# page 可传可不传
return {"关键词": keyword, "页码": page}
查询参数校验(长度、大小限制)
需要导入 Query
from fastapi import Query
@app.get("/demo")
def demo(
name: str = Query(min_length=2, max_length=10, description="用户名2-10字符"),
num: int = Query(ge=1, le=100) # 数字 1~100之间
):
return {"name": name, "num": num}
3. 请求体 Body(POST专用,传递JSON大数据)
GET不能携带请求体,所有复杂接口(对话、提交表单)都用 POST + Body
依靠 Pydantic BaseModel 定义JSON结构,自动校验。
完整标准结构:
from pydantic import BaseModel
# 定义请求体JSON结构
class ChatBody(BaseModel):
prompt: str
temperature: float = 0.7
stream: bool = False
@app.post("/llm/chat")
def llm_chat(body: ChatBody):
# body.prompt 直接获取json字段
return {"reply": f"你的问题:{body.prompt}"}
调用时提交JSON:
{"prompt":"什么是RAG","temperature":0.8,"stream":false}
四、路由标签、接口标题、文档注释(优化docs文档)
方便自动接口文档分类查看
@app.get("/user/{user_id}", summary="获取用户详情", tags=["用户模块"])
def get_user(user_id: int):
"""
根据用户ID查询用户信息
- user_id: 用户数字ID
"""
return {"id": user_id}
tags:给路由分组,docs页面会按分组展示接口。
五、重定向路由、返回HTML页面(拓展常用)
- 页面跳转 RedirectResponse
from fastapi.responses import RedirectResponse
@app.get(“/“)
def index():
# 访问根路径自动跳转到接口文档
return RedirectResponse(url="/docs")
2. 返回原生HTML文本
```python
from fastapi.responses import HTMLResponse
@app.get("/home", response_class=HTMLResponse)
def home():
return "<h1>首页页面</h1>"
六、路由前缀 APIRouter(大型项目拆分路由,重中之重)
项目接口多了之后,不能全部写在一个文件里,需要拆分:
用户接口、聊天接口、知识库接口分开文件管理,用 APIRouter
标准用法
from fastapi import APIRouter, FastAPI
app = FastAPI()
# 1. 创建路由对象,统一前缀 + 分组标签
user_router = APIRouter(prefix="/user", tags=["用户管理"])
# 路由自动拼接前缀:/user/list
@user_router.get("/list")
def user_list():
return ["用户1","用户2"]
# 注册到主应用
app.include_router(user_router)
实际项目目录拆分结构:
routers/
user.py # 用户相关路由
chat.py # LLM对话路由
knowledge.py # 知识库RAG路由
main.py # 引入所有路由并注册
七、路由匹配核心规则(高频踩坑点)
- 自上而下依次匹配,命中第一个路由就停止;
- 静态路由 > 带固定片段路由 > 纯动态变量路由;
- 路径参数顺序不能乱;
- 同一个url不能绑定多个相同请求方式函数;
- 路径参数、查询参数、body参数可以共存一个接口。
示例三者混用:
@app.post("/article/{article_id}")
def update_article(
article_id: int, # 路径参数
page: int = 1, # 查询参数
body: ChatBody # 请求体JSON
):
return {}
八、启动查看路由文档
启动命令:
uvicorn main:app --reload
- 交互式调试文档:
http://127.0.0.1:8000/docs - 静态文档:
http://127.0.0.1:8000/redoc
九、必会易错点汇总
- GET 请求无法接收 Body 请求体;
- 动态路径路由必须放在静态路由下方;
- 不加类型注解不会自动参数校验;
- 复杂JSON提交一律用 POST + Pydantic 请求体;
- 项目拆分路由必须使用 APIRouter,是企业开发规范;
- 同步函数、异步函数都可以绑定路由。
十、极简异步路由写法(对接LLM必备)
@app.post("/async_chat")
async def async_chat(body: ChatBody):
# 内部可以使用aiohttp异步调用本地Llama3
return {"ans": body.prompt}
需要我出5道路由代码练习题(填空+手写接口)给你自测吗?
本作品采用《CC 协议》,转载必须注明作者和本文链接
关于 LearnKu