第一个应用 #
Hello World #
让我们从最简单的 FastAPI 应用开始:
python
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def root():
return {'message': 'Hello World'}
运行应用 #
bash
uvicorn main:app --reload
访问 API #
bash
curl http://localhost:8000/
# {"message": "Hello World"}
代码解析 #
text
┌─────────────────────────────────────────────────────────────┐
│ FastAPI 应用结构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ from fastapi import FastAPI ← 导入 FastAPI 类 │
│ │
│ app = FastAPI() ← 创建应用实例 │
│ │
│ @app.get('/') ← 路由装饰器 │
│ async def root(): ← 路径操作函数 │
│ return {'message': 'Hello World'} │
│ │
└─────────────────────────────────────────────────────────────┘
1. 导入 FastAPI #
python
from fastapi import FastAPI
FastAPI 是核心类,用于创建应用实例。
2. 创建应用实例 #
python
app = FastAPI()
app 是 FastAPI 应用的主实例,所有路由和配置都通过它来定义。
3. 定义路由 #
python
@app.get('/')
@app.get('/') 是路由装饰器,定义了一个 GET 请求的路由。
4. 路径操作函数 #
python
async def root():
return {'message': 'Hello World'}
函数处理请求并返回响应。返回的字典会自动转换为 JSON。
HTTP 方法 #
FastAPI 支持所有标准 HTTP 方法:
python
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
def read_root():
return {'method': 'GET'}
@app.post('/')
def create_root():
return {'method': 'POST'}
@app.put('/')
def update_root():
return {'method': 'PUT'}
@app.delete('/')
def delete_root():
return {'method': 'DELETE'}
@app.patch('/')
def patch_root():
return {'method': 'PATCH'}
@app.options('/')
def options_root():
return {'method': 'OPTIONS'}
@app.head('/')
def head_root():
return {'method': 'HEAD'}
路径参数 #
基本路径参数 #
python
@app.get('/items/{item_id}')
def read_item(item_id: int):
return {'item_id': item_id}
访问 /items/5 返回:
json
{"item_id": 5}
多个路径参数 #
python
@app.get('/users/{user_id}/items/{item_id}')
def read_user_item(user_id: int, item_id: int):
return {'user_id': user_id, 'item_id': item_id}
路径参数类型 #
python
@app.get('/items/{item_id}')
def read_item(item_id: int): # 整数类型
return {'item_id': item_id}
@app.get('/users/{user_id}')
def read_user(user_id: str): # 字符串类型
return {'user_id': user_id}
@app.get('/files/{file_path:path}')
def read_file(file_path: str): # 路径类型(包含/)
return {'file_path': file_path}
枚举路径参数 #
python
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = 'alexnet'
resnet = 'resnet'
lenet = 'lenet'
app = FastAPI()
@app.get('/models/{model_name}')
def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {'model': model_name, 'message': 'Deep Learning FTW!'}
if model_name.value == 'lenet':
return {'model': model_name, 'message': 'LeCNN all the images'}
return {'model': model_name, 'message': 'Have some residuals'}
查询参数 #
基本查询参数 #
python
fake_items_db = [{'item_name': 'Foo'}, {'item_name': 'Bar'}, {'item_name': 'Baz'}]
@app.get('/items/')
def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]
访问 /items/?skip=0&limit=2 返回:
json
[
{"item_name": "Foo"},
{"item_name": "Bar"}
]
可选查询参数 #
python
from typing import Optional
@app.get('/items/{item_id}')
def read_item(item_id: str, q: Optional[str] = None):
if q:
return {'item_id': item_id, 'q': q}
return {'item_id': item_id}
必需查询参数 #
python
@app.get('/items/')
def read_items(skip: int, limit: int):
return {'skip': skip, 'limit': limit}
如果访问 /items/ 不带参数,会返回 422 错误。
查询参数类型转换 #
python
@app.get('/items/{item_id}')
def read_item(item_id: str, q: Optional[str] = None, short: bool = False):
item = {'item_id': item_id}
if q:
item.update({'q': q})
if not short:
item.update(
{'description': 'This is an amazing item'}
)
return item
访问 /items/foo?short=true 或 /items/foo?short=1 或 /items/foo?short=on 都会将 short 设为 True。
请求体 #
定义请求体模型 #
python
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.post('/items/')
def create_item(item: Item):
return item
请求体示例 #
发送 POST 请求到 /items/:
json
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
访问请求体属性 #
python
@app.post('/items/')
def create_item(item: Item):
item_dict = item.model_dump()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({'price_with_tax': price_with_tax})
return item_dict
请求体 + 路径参数 #
python
@app.put('/items/{item_id}')
def update_item(item_id: int, item: Item):
return {'item_id': item_id, **item.model_dump()}
请求体 + 路径参数 + 查询参数 #
python
@app.put('/items/{item_id}')
def update_item(item_id: int, item: Item, q: Optional[str] = None):
result = {'item_id': item_id, **item.model_dump()}
if q:
result.update({'q': q})
return result
响应模型 #
定义响应模型 #
python
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.post('/items/', response_model=Item)
def create_item(item: Item):
return item
响应模型过滤 #
python
class User(BaseModel):
username: str
email: str
password: str
class UserOut(BaseModel):
username: str
email: str
@app.post('/users/', response_model=UserOut)
def create_user(user: User):
return user
# 返回时自动过滤掉 password 字段
自动文档 #
Swagger UI #
访问 /docs 查看 Swagger UI 文档:
text
┌─────────────────────────────────────────────────────────────┐
│ Swagger UI │
├─────────────────────────────────────────────────────────────┤
│ │
│ http://localhost:8000/docs │
│ │
│ 功能: │
│ - 查看所有 API 端点 │
│ - 查看请求/响应格式 │
│ - 在线测试 API │
│ - 查看认证方式 │
│ │
└─────────────────────────────────────────────────────────────┘
ReDoc #
访问 /redoc 查看 ReDoc 文档:
text
┌─────────────────────────────────────────────────────────────┐
│ ReDoc │
├─────────────────────────────────────────────────────────────┤
│ │
│ http://localhost:8000/redoc │
│ │
│ 特点: │
│ - 更美观的界面 │
│ - 更适合阅读 │
│ - 三栏布局 │
│ - 搜索功能 │
│ │
└─────────────────────────────────────────────────────────────┘
自定义文档 #
python
from fastapi import FastAPI
app = FastAPI(
title='My API',
description='API description here',
version='0.1.0',
docs_url='/documentation',
redoc_url='/redocumentation'
)
调试模式 #
使用 print 调试 #
python
@app.get('/items/{item_id}')
def read_item(item_id: int, q: Optional[str] = None):
print(f'item_id: {item_id}, q: {q}')
return {'item_id': item_id, 'q': q}
使用 logging #
python
import logging
from fastapi import FastAPI
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
app = FastAPI()
@app.get('/')
def read_root():
logger.info('Processing request')
return {'message': 'Hello'}
使用调试器 #
在 VS Code 中设置断点,然后使用调试配置运行。
错误处理 #
HTTPException #
python
from fastapi import HTTPException
@app.get('/items/{item_id}')
def read_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail='Item not found')
return items_db[item_id]
自定义异常处理 #
python
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
class UnicornException(Exception):
def __init__(self, name: str):
self.name = name
app = FastAPI()
@app.exception_handler(UnicornException)
async def unicorn_exception_handler(request: Request, exc: UnicornException):
return JSONResponse(
status_code=418,
content={'message': f'Oops! {exc.name} did something.'},
)
@app.get('/unicorns/{name}')
def read_unicorn(name: str):
if name == 'yolo':
raise UnicornException(name=name)
return {'unicorn_name': name}
完整示例 #
python
from typing import Optional
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI(
title='Items API',
description='A simple items management API',
version='1.0.0'
)
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
items_db = {}
@app.get('/')
def read_root():
return {'message': 'Welcome to Items API'}
@app.get('/items/')
def read_items(skip: int = 0, limit: int = 10):
items = list(items_db.values())
return items[skip : skip + limit]
@app.get('/items/{item_id}')
def read_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail='Item not found')
return items_db[item_id]
@app.post('/items/{item_id}')
def create_item(item_id: int, item: Item):
if item_id in items_db:
raise HTTPException(status_code=400, detail='Item already exists')
items_db[item_id] = item
return item
@app.put('/items/{item_id}')
def update_item(item_id: int, item: Item):
if item_id not in items_db:
raise HTTPException(status_code=404, detail='Item not found')
items_db[item_id] = item
return item
@app.delete('/items/{item_id}')
def delete_item(item_id: int):
if item_id not in items_db:
raise HTTPException(status_code=404, detail='Item not found')
del items_db[item_id]
return {'message': 'Item deleted'}
下一步 #
现在你已经创建了第一个 FastAPI 应用,接下来学习 路径操作,深入了解 FastAPI 的路由系统!
最后更新:2026-03-29