213 lines
7.0 KiB
Python
213 lines
7.0 KiB
Python
"""
|
|
人脸特征值的Pydantic模型
|
|
用于数据验证和序列化
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Optional, List, Dict, Any
|
|
from pydantic import BaseModel, Field, field_validator, ConfigDict, model_validator
|
|
from enum import IntEnum
|
|
|
|
|
|
# 枚举定义(与数据库模型一致)
|
|
class FeatureStatus(IntEnum):
|
|
NOT_STARTED = 0
|
|
PROCESSING = 1
|
|
SUCCESS = 2
|
|
FAILED = 3
|
|
|
|
|
|
# 基础模型
|
|
class FaceFeatureBase(BaseModel):
|
|
"""基础模型,包含所有字段"""
|
|
person_id: int = Field(..., description="人员ID", gt=0)
|
|
feature_type: Optional[int] = Field(None, description="模型版本", ge=0)
|
|
feature_data: Optional[bytes] = Field(None, description="特征值(二进制)")
|
|
pic_id: Optional[str] = Field(None, description="图片ID", max_length=255)
|
|
status: FeatureStatus = Field(
|
|
default=FeatureStatus.NOT_STARTED,
|
|
description="计算状态"
|
|
)
|
|
start_time: Optional[datetime] = Field(None, description="计算开始时间")
|
|
finish_time: Optional[datetime] = Field(None, description="计算结束时间")
|
|
|
|
@field_validator('feature_data', mode='before')
|
|
@classmethod
|
|
def validate_feature_data(cls, v):
|
|
"""验证特征数据"""
|
|
if v is not None and not isinstance(v, bytes):
|
|
if isinstance(v, str):
|
|
# 尝试从hex字符串转换
|
|
try:
|
|
return bytes.fromhex(v)
|
|
except ValueError:
|
|
raise ValueError("feature_data must be valid hex string or bytes")
|
|
else:
|
|
raise ValueError("feature_data must be bytes or hex string")
|
|
return v
|
|
|
|
|
|
# 创建模型
|
|
class FaceFeatureCreate(FaceFeatureBase):
|
|
"""创建特征记录模型"""
|
|
# 创建时不指定ID和时间
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"person_id": 1001,
|
|
"feature_type": 1,
|
|
"pic_id": "img_20250101_001",
|
|
"status": 0
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
class FaceFeatureUpdate(BaseModel):
|
|
"""更新特征记录模型"""
|
|
feature_type: Optional[int] = Field(None, description="模型版本", ge=0)
|
|
feature_data: Optional[bytes] = Field(None, description="特征值(二进制)")
|
|
pic_id: Optional[str] = Field(None, description="图片ID", max_length=255)
|
|
status: Optional[FeatureStatus] = Field(None, description="计算状态")
|
|
start_time: Optional[datetime] = Field(None, description="计算开始时间")
|
|
finish_time: Optional[datetime] = Field(None, description="计算结束时间")
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"status": 2,
|
|
"finish_time": "2024-01-01T12:00:00Z"
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
# 查询参数模型
|
|
class FaceFeatureQuery(BaseModel):
|
|
"""特征记录查询参数"""
|
|
person_id: Optional[int] = Field(None, description="人员ID", gt=0)
|
|
feature_type: Optional[int] = Field(None, description="模型版本", ge=0)
|
|
status: Optional[FeatureStatus] = Field(None, description="计算状态")
|
|
start_date: Optional[datetime] = Field(None, description="开始时间")
|
|
end_date: Optional[datetime] = Field(None, description="结束时间")
|
|
has_feature_data: Optional[bool] = Field(None, description="是否有特征数据")
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"person_id": 1001,
|
|
"status": 2,
|
|
"start_date": "2024-01-01T00:00:00Z"
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
# 响应模型
|
|
class FaceFeatureResponse(FaceFeatureBase):
|
|
"""特征记录响应模型"""
|
|
id: int
|
|
created_time: datetime
|
|
|
|
# 计算字段(将在验证后设置)
|
|
status_name: Optional[str] = None
|
|
is_completed: Optional[bool] = None
|
|
processing_time: Optional[float] = None
|
|
has_feature_data: Optional[bool] = None
|
|
|
|
@model_validator(mode='after')
|
|
def set_computed_fields(self):
|
|
"""设置所有计算字段"""
|
|
# 状态名称
|
|
try:
|
|
self.status_name = FeatureStatus(self.status).name
|
|
except ValueError:
|
|
self.status_name = f"未知状态({self.status})"
|
|
|
|
# 是否完成
|
|
self.is_completed = self.status in [FeatureStatus.SUCCESS, FeatureStatus.FAILED]
|
|
|
|
# 处理时间
|
|
if self.start_time and self.finish_time:
|
|
self.processing_time = (self.finish_time - self.start_time).total_seconds()
|
|
|
|
# 是否有特征数据
|
|
self.has_feature_data = self.feature_data is not None and len(self.feature_data) > 0
|
|
|
|
return self
|
|
|
|
model_config = ConfigDict(
|
|
from_attributes=True,
|
|
populate_by_name=True,
|
|
json_schema_extra={
|
|
"example": {
|
|
"id": 1,
|
|
"person_id": 1001,
|
|
"feature_type": 1,
|
|
"status": 2,
|
|
"status_name": "SUCCESS",
|
|
"created_time": "2024-01-01T10:00:00Z",
|
|
"pic_id": "img_20250101_001",
|
|
"start_time": "2024-01-01T10:00:00Z",
|
|
"finish_time": "2024-01-01T10:00:05Z",
|
|
"is_completed": True,
|
|
"processing_time": 5.0,
|
|
"has_feature_data": True
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
class FaceFeatureListResponse(BaseModel):
|
|
"""特征记录列表响应"""
|
|
total: int = Field(..., description="总记录数")
|
|
items: List[FaceFeatureResponse] = Field(..., description="记录列表")
|
|
page: Optional[int] = Field(None, description="当前页码")
|
|
page_size: Optional[int] = Field(None, description="每页数量")
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"total": 100,
|
|
"page": 1,
|
|
"page_size": 20,
|
|
"items": []
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
# 批量操作模型
|
|
class BatchFaceFeatureCreate(BaseModel):
|
|
"""批量创建特征记录"""
|
|
items: List[FaceFeatureCreate] = Field(..., description="特征记录列表", min_items=1, max_items=1000)
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"items": [
|
|
{"person_id": 1001, "feature_type": 1},
|
|
{"person_id": 1002, "feature_type": 1}
|
|
]
|
|
}
|
|
}
|
|
)
|
|
|
|
|
|
class FaceFeatureStatsResponse(BaseModel):
|
|
"""特征记录统计响应"""
|
|
total_count: int = Field(..., description="总记录数")
|
|
by_status: Dict[str, int] = Field(..., description="按状态统计")
|
|
by_feature_type: Dict[str, int] = Field(..., description="按特征类型统计")
|
|
avg_processing_time: Optional[float] = Field(None, description="平均处理时间(秒)")
|
|
|
|
model_config = ConfigDict(
|
|
json_schema_extra={
|
|
"example": {
|
|
"total_count": 1000,
|
|
"by_status": {"SUCCESS": 800, "PROCESSING": 100, "FAILED": 100},
|
|
"by_feature_type": {"1": 500, "2": 500},
|
|
"avg_processing_time": 5.2
|
|
}
|
|
}
|
|
) |