【剪映小助手源码精讲】16_请求响应模型设计

27 阅读9分钟

第16章:请求响应模型设计

16.1 概述

剪映小助手采用 Pydantic 作为数据验证和序列化的核心库,通过强类型的数据模型确保 API 请求和响应的数据格式的一致性和可靠性。请求响应模型设计遵循 RESTful API 设计原则,提供了清晰、一致、易于维护的数据交互规范。

本章将详细介绍剪映小助手中的请求响应模型设计,包括 Pydantic 模型基础、请求模型设计规范、响应模型结构定义、数据验证机制以及模型复用与继承等核心内容。

16.2 Pydantic 模型基础

16.2.1 模型定义原则

剪映小助手中的所有数据模型都基于 Pydantic 的 BaseModel 构建,遵循以下设计原则:

  1. 类型安全: 所有字段都必须明确定义类型
  2. 验证机制: 内置数据验证,确保数据有效性
  3. 文档友好: 通过 Field 描述提供清晰的字段说明
  4. 默认值: 合理使用默认值,提高接口易用性
  5. 继承复用: 通过继承机制实现模型复用

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 命名规范

  1. 请求模型: {操作}Request 格式,如 AddVideosRequest
  2. 响应模型: {操作}Response 格式,如 AddVideosResponse
  3. 嵌套模型: 使用描述性名称,如 VideoInfo, AudioInfo
  4. 通用模型: 使用通用前缀,如 BaseRequest, BaseResponse

16.10.2 设计原则

  1. 单一职责: 每个模型只负责一个特定的功能
  2. 类型安全: 明确定义每个字段的类型
  3. 验证优先: 在模型层面进行数据验证
  4. 文档完整: 提供清晰的字段描述和示例
  5. 向后兼容: 谨慎修改现有模型的结构

16.10.3 性能考虑

  1. 避免深层嵌套: 减少模型的嵌套层级
  2. 合理使用默认值: 减少不必要的数据传输
  3. 缓存验证结果: 对于频繁验证的模型考虑缓存
  4. 异步处理: 在适当的时候使用异步验证

16.11 总结

剪映小助手的请求响应模型设计充分体现了现代 API 设计的最佳实践。通过 Pydantic 框架,我们实现了:

  1. 强类型验证: 确保数据的完整性和有效性
  2. 清晰的结构: 统一的命名和设计规范
  3. 完善的文档: 自动生成 API 文档
  4. 易于维护: 模块化和可复用的设计
  5. 高性能: 优化的序列化和验证机制

这种设计不仅提高了开发效率,还大大增强了系统的可靠性和可维护性,为剪映小助手的稳定运行提供了坚实的基础。


相关资源