4、FastAPI入门:FastAPI安装与Hello World、路径参数与查询参数、请求体与响应模型
好,咱们开始进入FastAPI的世界。
说实话,我最早接触FastAPI是在一个紧急的API重构项目里。当时Django太重,Flask又缺类型校验,折腾得够呛。后来试了试FastAPI,嗯,真香。它把Python的类型提示玩出了花,性能还直追Go写的框架。今天咱们就从零开始,把FastAPI的底子打扎实。
4.1 安装FastAPI
安装其实很简单,一行命令搞定。但我建议你最好在虚拟环境里操作,别污染全局的Python环境。
pip install fastapi
pip install uvicorn # 这是ASGI服务器,用来跑FastAPI应用
我个人习惯把常用依赖写进 requirements.txt:
fastapi==0.104.1
uvicorn==0.24.0
然后执行 pip install -r requirements.txt 就行。
python-dotenv 包,方便管理环境变量。我在项目中经常这么干。
4.2 Hello World:第一个FastAPI应用
来,写个最简单的接口。新建一个 main.py:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
启动命令:
uvicorn main:app --reload
打开浏览器访问 http://127.0.0.1:8000,你会看到:
{"message": "Hello World"}
是不是很清爽?--reload 参数让代码修改后自动重启,开发时特别方便。不过生产环境千万别加这个参数,我见过有人上线忘了去掉,结果服务器CPU飙到100%。
/docs 就能看到Swagger UI,访问 /redoc 能看到ReDoc。这个特性在前后端联调时简直救命。
4.3 路径参数
路径参数就是从URL路径中提取变量。比如你想根据用户ID查信息:
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id, "name": f"User_{user_id}"}
这里 user_id 被声明为 int 类型。如果你传一个非数字的值,比如 /users/abc,FastAPI会自动返回422错误。为什么?因为它内置了Pydantic的校验机制。
我曾经在项目中遇到过一个问题:路径参数和查询参数搞混了。比如 /items/{item_id} 和 /items?item_id=123 是两回事。路径参数是URL结构的一部分,查询参数是 ? 后面的键值对。别搞反了。
路径参数还支持枚举类型:
from enum import Enum
class UserType(str, Enum):
admin = "admin"
user = "user"
guest = "guest"
@app.get("/users/{user_type}/{user_id}")
def get_user_by_type(user_type: UserType, user_id: int):
return {"type": user_type, "id": user_id}
这样 /users/admin/123 能正常访问,但 /users/superadmin/123 就会报错。嗯,这里要注意:枚举值必须严格匹配。
4.4 查询参数
查询参数就是URL中 ? 后面的部分。比如分页、过滤条件:
@app.get("/items/")
def list_items(skip: int = 0, limit: int = 10):
return {"skip": skip, "limit": limit}
访问 /items/?skip=0&limit=5,返回:
{"skip": 0, "limit": 5}
查询参数可以有默认值,也可以声明为可选:
from typing import Optional
@app.get("/items/")
def list_items(
skip: int = 0,
limit: int = 10,
q: Optional[str] = None # 可选参数
):
result = {"skip": skip, "limit": limit}
if q:
result["q"] = q
return result
你想想看,如果 q 没传,它就是 None,不会报错。这种设计在搜索接口里特别常见。
4.5 请求体与响应模型
请求体就是POST、PUT等请求中携带的JSON数据。FastAPI用Pydantic模型来定义请求体结构:
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
@app.post("/items/")
def create_item(item: Item):
return {"item_name": item.name, "item_price": item.price}
发送POST请求时,请求体必须是这样的JSON:
{
"name": "笔记本电脑",
"price": 5999.00,
"is_offer": true
}
如果 is_offer 不传,它默认为 None。如果传了类型不对的值,比如 price: "免费",FastAPI会直接返回422错误,告诉你字段类型不匹配。
响应模型就更厉害了。你可以定义返回的数据结构,FastAPI会自动过滤掉多余字段:
class ItemResponse(BaseModel):
name: str
price: float
# 注意:这里没有 is_offer
@app.post("/items/", response_model=ItemResponse)
def create_item(item: Item):
# 假设数据库里存了更多字段
db_item = {
"name": item.name,
"price": item.price,
"is_offer": item.is_offer,
"internal_code": "SECRET_123" # 这个字段不会返回
}
return db_item
返回给客户端的数据只包含 name 和 price,internal_code 被自动过滤掉了。说白了,响应模型就是一道防火墙,防止你泄露敏感字段。
4.6 综合示例:一个完整的CRUD雏形
把上面学的东西串起来,写个简单的物品管理接口:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import Optional, List
app = FastAPI()
# 模拟数据库
items_db = {}
class Item(BaseModel):
name: str
price: float
is_offer: Optional[bool] = None
class ItemResponse(BaseModel):
id: int
name: str
price: float
@app.post("/items/", response_model=ItemResponse)
def create_item(item: Item):
item_id = len(items_db) + 1
items_db[item_id] = item
return ItemResponse(id=item_id, name=item.name, price=item.price)
@app.get("/items/{item_id}", response_model=ItemResponse)
def get_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail="Item not found")
item = items_db[item_id]
return ItemResponse(id=item_id, name=item.name, price=item.price)
@app.get("/items/")
def list_items(skip: int = 0, limit: int = 10):
all_items = [
ItemResponse(id=i, name=item.name, price=item.price)
for i, item in items_db.items()
]
return all_items[skip: skip + limit]
这个例子虽然简单,但包含了路径参数、查询参数、请求体、响应模型、错误处理等核心概念。你可以在 /docs 里直接测试每个接口,非常直观。
/docs 页面。它不仅能测试接口,还能看到每个参数的校验规则。比Postman还方便。
好了,FastAPI的入门就到这里。下一章咱们会深入依赖注入和中间件,那才是FastAPI真正发力的地方。记住:先跑通Hello World,再理解路径和查询参数的区别,最后用Pydantic模型把请求和响应管起来。这三步走稳了,后面的路就好走了。