第一个应用 #

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