明白。FastAPI 基础可以按 7 个概念学,不要一开始就陷进项目结构。
1. FastAPI 是什么
FastAPI 是 Python 的 Web API 框架。你写普通 Python 函数,它帮你处理:
- HTTP 路由
- JSON 请求和响应
- 参数校验
- 自动 API 文档
- 错误返回
- 异步接口
官方基础示例也是从 FastAPI()、路由装饰器、启动服务、访问 /docs 开始。参考:FastAPI First Steps。
2. 最小程序
下载依赖: uvicorn:服务器
uv install python 3.11
uv add 'fastapi[standard]@latest'
uv add 'uvicorn[standard]'
新建 main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello FastAPI"}
启动:
uvicorn main:app --reload
含义:
main:文件名main.pyapp:代码里的app = FastAPI()--reload:开发模式,代码变化自动重启
访问:
http://127.0.0.1:8000/
http://127.0.0.1:8000/docs
/docs 是自动生成的接口调试页面。
3. 路由:GET / POST / PUT / DELETE
路由就是“URL + HTTP 方法”。
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/items")
def create_item():
return {"message": "created"}
@app.put("/items/{item_id}")
def update_item(item_id: int):
return {"item_id": item_id, "message": "updated"}
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
return {"item_id": item_id, "message": "deleted"}
常见习惯:
GET:查询POST:创建或执行动作PUT/PATCH:更新DELETE:删除
4. 参数:路径参数、查询参数、请求体
路径参数来自 URL 中间(常用于查询单个 item):
@app.get("/items/{item_id}")
def get_item(item_id: int):
return {"item_id": item_id}
访问:
/items/123
FastAPI 会自动把 "123" 转成 int。如果传 /items/abc,会自动报参数错误。
查询参数来自 ? 后面(常用于查询 item 列表):
@app.get("/search")
def search(q: str, limit: int = 10):
return {"q": q, "limit": limit}
访问:
/search?q=aspirin&limit=5
请求体一般用于 POST,用 Pydantic 模型声明。官方文档也强调,Pydantic 模型会被 FastAPI 识别为 request body。参考:FastAPI Request Body。
from pydantic import BaseModel
class MoleculeRequest(BaseModel):
smiles: str
name: str | None = None
@app.post("/molecules")
def create_molecule(data: MoleculeRequest):
return {
"smiles": data.smiles,
"name": data.name,
}
请求 JSON:
{
"smiles": "CCO",
"name": "ethanol"
}
5. 返回 JSON
你直接返回 dict、list、Pydantic model,FastAPI 会自动转成 JSON:
@app.get("/molecules")
def list_molecules():
return [
{"name": "ethanol", "smiles": "CCO"},
{"name": "aspirin", "smiles": "CC(=O)Oc1ccccc1C(=O)O"},
]
6. 主动返回错误
接口里不要用普通 return {"error": ...} 混过去,应该用 HTTPException:
from fastapi import HTTPException
@app.get("/molecules/{molecule_id}")
def get_molecule(molecule_id: int):
if molecule_id <= 0:
raise HTTPException(status_code=400, detail="molecule_id must be positive")
return {"id": molecule_id}
常见状态码:
200:成功201:创建成功400:请求参数不合法401:未登录403:无权限404:资源不存在500:服务端错误
7. async 和普通 def
两种都能写:
@app.get("/sync")
def sync_api():
return {"mode": "sync"}
@app.get("/async")
async def async_api():
return {"mode": "async"}
简单理解:
- 普通计算、调用同步库:用
def - 调数据库、HTTP 请求、文件 IO,并且库支持 async:用
async def
初学阶段先用 def 就够了,别为了“看起来高级”乱用 async。
一个完整基础例子
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title="Drug Discovery API")
class SmilesRequest(BaseModel):
smiles: str = Field(min_length=1)
@app.get("/health")
def health():
return {"status": "ok"}
@app.get("/molecules/{molecule_id}")
def get_molecule(molecule_id: int):
if molecule_id <= 0:
raise HTTPException(status_code=400, detail="molecule_id must be positive")
return {
"id": molecule_id,
"name": "ethanol",
"smiles": "CCO",
}
@app.get("/search")
def search_molecules(q: str, limit: int = 10):
return {
"query": q,
"limit": limit,
"results": [],
}
@app.post("/smiles/validate")
def validate_smiles(data: SmilesRequest):
is_valid = data.smiles.strip() != ""
return {
"smiles": data.smiles,
"is_valid": is_valid,
}
你现在只需要掌握这条主线:
定义 app
-> 写路由
-> 声明参数
-> 用 Pydantic 接 JSON
-> 返回 dict
-> 用 HTTPException 报错
-> 去 /docs 测试