第16章:请求响应模型设计
16.1 概述
剪映小助手采用 Pydantic 作为数据验证和序列化的核心库,通过强类型的数据模型确保 API 请求和响应的数据格式的一致性和可靠性。请求响应模型设计遵循 RESTful API 设计原则,提供了清晰、一致、易于维护的数据交互规范。
本章将详细介绍剪映小助手中的请求响应模型设计,包括 Pydantic 模型基础、请求模型设计规范、响应模型结构定义、数据验证机制以及模型复用与继承等核心内容。
16.2 Pydantic 模型基础
16.2.1 模型定义原则
剪映小助手中的所有数据模型都基于 Pydantic 的 BaseModel 构建,遵循以下设计原则:
- 类型安全: 所有字段都必须明确定义类型
- 验证机制: 内置数据验证,确保数据有效性
- 文档友好: 通过 Field 描述提供清晰的字段说明
- 默认值: 合理使用默认值,提高接口易用性
- 继承复用: 通过继承机制实现模型复用
16.2.2 基础模型结构
from pydantic import BaseModel, Field
from typing import List, Optional
class BaseRequest(BaseModel):
"""请求模型基类"""
pass
class BaseResponse(BaseModel):
"""响应模型基类"""
pass
16.3 请求模型设计规范
16.3.1 通用请求模式
剪映小助手的请求模型遵循统一的命名和设计规范:
创建类请求
class CreateDraftRequest(BaseModel):
"""创建草稿请求参数"""
height: int = Field(default=1080, ge=1, description="视频高度")
width: int = Field(default=1920, ge=1, description="视频宽度")
添加类请求
class AddVideosRequest(BaseModel):
"""批量添加视频请求参数"""
draft_url: str = Field(default="", description="草稿URL")
video_infos: str = Field(default="", description="视频信息列表, 用JSON字符串表示")
alpha: float = Field(default=1.0, description="全局透明度[0, 1]")
scale_x: float = Field(default=1.0, description="X轴缩放比例, 建议范围[0.1, 5.0]")
scale_y: float = Field(default=1.0, description="Y轴缩放比例, 建议范围[0.1, 5.0]")
transform_x: int = Field(default=0, description="X轴位置偏移(像素)")
transform_y: int = Field(default=0, description="Y轴位置偏移(像素)")
查询类请求
class GetDraftRequest(BaseModel):
"""获取草稿请求参数"""
draft_id: str = Field(..., min_length=20, max_length=32, description="草稿ID")
16.3.2 字段验证规则
字符串字段验证
draft_url: str = Field(..., description="草稿URL") # 必填字段
draft_id: str = Field(..., min_length=20, max_length=32, description="草稿ID") # 长度限制
video_infos: str = Field(default="", description="视频信息列表") # 默认值
数值字段验证
height: int = Field(default=1080, ge=1, description="视频高度") # 最小值限制
alpha: float = Field(default=1.0, description="全局透明度") # 浮点数
scale_x: float = Field(default=1.0, description="X轴缩放比例") # 建议范围注释
列表字段验证
video_ids: List[str] = Field(default=[], description="视频ID列表") # 字符串列表
audio_ids: List[str] = Field(default=[], description="音频ID列表") # 默认空列表
16.3.3 JSON 字符串处理
对于复杂的嵌套数据结构,采用 JSON 字符串格式进行传输:
class AddAudiosRequest(BaseModel):
"""批量添加音频请求参数"""
draft_url: str = Field(..., description="草稿URL")
audio_infos: str = Field(..., description="音频信息列表, 用JSON字符串表示")
对应的 JSON 数据结构示例:
{
"draft_url": "https://example.com/draft",
"audio_infos": "[{\"audio_url\": \"https://example.com/audio.mp3\", \"start\": 0, \"end\": 1000000, \"volume\": 0.8}]"
}
16.4 响应模型结构定义
16.4.1 通用响应模式
基础响应模型
class AddVideosResponse(BaseModel):
"""添加视频响应参数"""
draft_url: str = Field(default="", description="草稿URL")
track_id: str = Field(default="", description="轨道ID")
video_ids: List[str] = Field(default=[], description="视频ID列表")
segment_ids: List[str] = Field(default=[], description="片段ID列表")
状态查询响应
class GenVideoStatusResponse(BaseModel):
"""查询视频生成状态的响应模型"""
draft_url: str = Field(..., description="草稿URL")
status: str = Field(..., description="任务状态:pending=等待中,processing=处理中,completed=已完成,failed=失败")
progress: int = Field(..., description="任务进度(0-100)")
video_url: str = Field(default="", description="生成的视频URL(仅在completed状态时有值)")
error_message: str = Field(default="", description="错误信息(仅在failed状态时有值)")
created_at: Optional[str] = Field(default=None, description="任务创建时间")
started_at: Optional[str] = Field(default=None, description="任务开始时间")
completed_at: Optional[str] = Field(default=None, description="任务完成时间")
16.4.2 状态码和错误处理
简单响应模型
class GenVideoResponse(BaseModel):
"""生成视频响应参数"""
message: str = Field(..., description="响应消息")
文件列表响应
class GetDraftResponse(BaseModel):
"""获取草稿响应参数"""
files: List[str] = Field(default=[], description="文件列表")
16.5 数据验证机制
16.5.1 自动验证
Pydantic 提供了强大的自动验证功能:
# 数值范围验证
height: int = Field(default=1080, ge=1, description="视频高度")
# 字符串长度验证
draft_id: str = Field(..., min_length=20, max_length=32, description="草稿ID")
# 正则表达式验证(扩展)
email: str = Field(..., regex=r'^[\w\.-]+@[\w\.-]+\.\w+$', description="邮箱地址")
16.5.2 自定义验证器
对于复杂的业务逻辑验证,可以添加自定义验证器:
from pydantic import validator
class AddVideosRequest(BaseModel):
video_infos: str = Field(default="", description="视频信息列表")
@validator('video_infos')
def validate_video_infos(cls, v):
if v:
try:
import json
data = json.loads(v)
if not isinstance(data, list):
raise ValueError('video_infos must be a JSON array')
return v
except json.JSONDecodeError:
raise ValueError('video_infos must be valid JSON')
return v
16.5.3 嵌套模型验证
对于复杂的数据结构,使用嵌套模型进行验证:
from typing import Optional
from pydantic import BaseModel, Field
class VideoInfo(BaseModel):
"""视频信息模型"""
video_url: str = Field(..., description="视频URL")
width: int = Field(..., ge=1, description="视频宽度")
height: int = Field(..., ge=1, description="视频高度")
start: int = Field(..., ge=0, description="开始时间(微秒)")
end: int = Field(..., ge=0, description="结束时间(微秒)")
duration: int = Field(..., ge=1, description="持续时间(微秒)")
volume: float = Field(default=1.0, ge=0.0, le=1.0, description="音量")
class AddVideosRequest(BaseModel):
"""批量添加视频请求参数"""
draft_url: str = Field(..., description="草稿URL")
video_infos: List[VideoInfo] = Field(..., description="视频信息列表")
16.6 模型复用与继承
16.6.1 基础模型定义
定义通用的基础模型,供其他模型继承:
class BaseDraftRequest(BaseModel):
"""草稿请求基础模型"""
draft_url: str = Field(..., description="草稿URL")
class BaseDraftResponse(BaseModel):
"""草稿响应基础模型"""
draft_url: str = Field(default="", description="草稿URL")
16.6.2 模型继承应用
通过继承实现模型的复用:
class AddVideosRequest(BaseDraftRequest):
"""批量添加视频请求参数"""
video_infos: str = Field(default="", description="视频信息列表")
alpha: float = Field(default=1.0, description="全局透明度")
class AddAudiosRequest(BaseDraftRequest):
"""批量添加音频请求参数"""
audio_infos: str = Field(..., description="音频信息列表")
class AddVideosResponse(BaseDraftResponse):
"""添加视频响应参数"""
track_id: str = Field(default="", description="轨道ID")
video_ids: List[str] = Field(default=[], description="视频ID列表")
segment_ids: List[str] = Field(default=[], description="片段ID列表")
16.6.3 泛型模型设计
使用泛型实现更灵活的模型设计:
from typing import Generic, TypeVar, List
T = TypeVar('T')
class BaseResponse(BaseModel, Generic[T]):
"""通用响应模型"""
code: int = Field(default=200, description="响应码")
message: str = Field(default="success", description="响应消息")
data: Optional[T] = Field(default=None, description="响应数据")
class ListResponse(BaseModel, Generic[T]):
"""列表响应模型"""
total: int = Field(..., description="总数")
items: List[T] = Field(default=[], description="数据列表")
page: int = Field(default=1, description="当前页码")
size: int = Field(default=10, description="每页大小")
16.7 模型文档化
16.7.1 字段描述
通过 Field 的 description 参数提供清晰的字段说明:
class AddVideosRequest(BaseModel):
"""批量添加视频请求参数
用于向指定草稿中添加多个视频素材,支持设置视频的基本属性如透明度、缩放比例、位置偏移等。
视频信息通过 JSON 字符串传递,每个视频可以设置独立的播放时间范围和属性。
"""
draft_url: str = Field(..., description="目标草稿的完整URL地址,用于标识要操作的草稿")
video_infos: str = Field(..., description="视频信息列表,JSON字符串格式,包含视频的URL、尺寸、时间范围等属性")
alpha: float = Field(default=1.0, description="全局透明度,范围0-1,1表示完全不透明")
16.7.2 模型配置
通过 Config 类配置模型行为:
class AddVideosRequest(BaseModel):
draft_url: str = Field(..., description="草稿URL")
class Config:
# 允许字段赋值时使用别名
allow_population_by_field_name = True
# 验证赋值操作
validate_assignment = True
# 使用枚举值
use_enum_values = True
# 模式验证
validate_all = True
16.8 模型使用示例
16.8.1 模型实例化
# 创建请求模型
request = AddVideosRequest(
draft_url="https://example.com/draft",
video_infos='[{"video_url": "https://example.com/video.mp4", "width": 1920, "height": 1080}]',
alpha=0.8
)
# 模型验证
try:
validated_data = AddVideosRequest(**raw_data)
except ValidationError as e:
print(f"验证错误: {e}")
16.8.2 模型序列化
# 模型转字典
data_dict = request.dict()
# 模型转JSON
json_str = request.json()
# 包含字段说明的架构信息
schema = request.schema()
16.8.3 在路由中的使用
from fastapi import FastAPI, HTTPException
from src.schemas.add_videos import AddVideosRequest, AddVideosResponse
app = FastAPI()
@app.post("/add_videos", response_model=AddVideosResponse)
async def add_videos(request: AddVideosRequest):
"""添加视频接口"""
try:
# 业务逻辑处理
result = process_add_videos(request)
return AddVideosResponse(**result)
except Exception as e:
raise HTTPException(status_code=400, detail=str(e))
16.9 模型测试与验证
16.9.1 单元测试
import pytest
from src.schemas.add_videos import AddVideosRequest
def test_add_videos_request():
"""测试添加视频请求模型"""
# 正常情况
request = AddVideosRequest(
draft_url="https://example.com/draft",
video_infos='[{"video_url": "test.mp4", "width": 1920, "height": 1080}]'
)
assert request.draft_url == "https://example.com/draft"
assert request.alpha == 1.0 # 默认值
# 验证错误情况
with pytest.raises(ValidationError):
AddVideosRequest(
draft_url="", # 空字符串应该失败
video_infos="invalid_json"
)
16.9.2 性能优化
from pydantic import BaseModel, Field
from typing import Optional
class OptimizedRequest(BaseModel):
"""优化的请求模型"""
# 使用较小的字段名减少序列化开销
url: str = Field(..., description="草稿URL")
data: str = Field(..., description="数据")
class Config:
# 跳过未设置字段的验证
validate_all = False
# 使用更快的JSON解析器
json_loads = orjson.loads
json_dumps = orjson.dumps
16.10 最佳实践
16.10.1 命名规范
- 请求模型:
{操作}Request格式,如AddVideosRequest - 响应模型:
{操作}Response格式,如AddVideosResponse - 嵌套模型: 使用描述性名称,如
VideoInfo,AudioInfo - 通用模型: 使用通用前缀,如
BaseRequest,BaseResponse
16.10.2 设计原则
- 单一职责: 每个模型只负责一个特定的功能
- 类型安全: 明确定义每个字段的类型
- 验证优先: 在模型层面进行数据验证
- 文档完整: 提供清晰的字段描述和示例
- 向后兼容: 谨慎修改现有模型的结构
16.10.3 性能考虑
- 避免深层嵌套: 减少模型的嵌套层级
- 合理使用默认值: 减少不必要的数据传输
- 缓存验证结果: 对于频繁验证的模型考虑缓存
- 异步处理: 在适当的时候使用异步验证
16.11 总结
剪映小助手的请求响应模型设计充分体现了现代 API 设计的最佳实践。通过 Pydantic 框架,我们实现了:
- 强类型验证: 确保数据的完整性和有效性
- 清晰的结构: 统一的命名和设计规范
- 完善的文档: 自动生成 API 文档
- 易于维护: 模块化和可复用的设计
- 高性能: 优化的序列化和验证机制
这种设计不仅提高了开发效率,还大大增强了系统的可靠性和可维护性,为剪映小助手的稳定运行提供了坚实的基础。
相关资源
- GitHub代码仓库: github.com/Hommy-maste…
- Gitee代码仓库: gitee.com/taohongmin-…
- API文档地址: docs.jcaigc.cn