Files
kami_apple_exchage/backend/app/schemas/user_data.py
danial 5c486e34d3 docs(项目): 添加项目文档并进行代码调整
- 新增 CODEBUDDY.md、GEMINI.md、GEMINI_CN.md 等项目文档
- 更新 Dockerfile 和其他配置文件
- 优化部分代码结构,如 orders.py、tasks.py 等
- 新增 .dockerignore 文件
2025-09-12 19:38:24 +08:00

127 lines
4.5 KiB
Python

"""
用户数据相关的Pydantic模型
"""
from datetime import datetime
from pydantic import BaseModel, Field, field_validator, ConfigDict
class UserDataBase(BaseModel):
"""用户数据基础模型"""
first_name: str = Field(..., description="名字", max_length=255)
last_name: str = Field(..., description="姓氏", max_length=255)
email: str = Field(..., description="邮箱", max_length=255)
phone: str = Field(..., description="电话", max_length=50)
street_address: str = Field(..., description="街道地址", max_length=500)
city: str = Field(..., description="城市", max_length=255)
state: str = Field(..., description="州/省", max_length=255)
zip_code: str = Field(..., description="邮编", max_length=20)
@field_validator("email")
@classmethod
def validate_email(cls, v):
"""验证邮箱格式"""
import re
pattern = r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$"
if not re.match(pattern, v):
raise ValueError("邮箱格式不正确")
return v
class UserDataCreate(UserDataBase):
"""创建用户数据请求模型"""
pass
class UserDataUpdate(BaseModel):
"""更新用户数据请求模型"""
first_name: str | None = Field(None, description="名字", max_length=255)
last_name: str | None = Field(None, description="姓氏", max_length=255)
email: str | None = Field(None, description="邮箱", max_length=255)
phone: str | None = Field(None, description="电话", max_length=50)
street_address: str | None = Field(None, description="街道地址", max_length=500)
city: str | None = Field(None, description="城市", max_length=255)
state: str | None = Field(None, description="州/省", max_length=255)
zip_code: str | None = Field(None, description="邮编", max_length=20)
class UserDataResponse(UserDataBase):
"""用户数据响应模型"""
id: str = Field(..., description="用户数据ID")
created_at: str = Field(..., description="创建时间")
updated_at: str = Field(..., description="更新时间")
model_config = ConfigDict(from_attributes=True)
class UserDataListResponse(BaseModel):
"""用户数据列表响应模型"""
items: list[UserDataResponse]
total: int
page: int
size: int
pages: int
class UserDataUploadResponse(BaseModel):
"""用户数据上传响应模型"""
user_data: UserDataResponse
message: str = Field(..., description="响应消息")
class UserInfoResponse(BaseModel):
"""用户信息响应模型 - 与数据表字段完全一致"""
id: str = Field(..., description="用户数据唯一标识")
first_name: str = Field(..., description="名字")
last_name: str = Field(..., description="姓氏")
email: str = Field(..., description="邮箱地址")
phone: str = Field(..., description="电话号码")
street_address: str = Field(..., description="街道地址")
city: str = Field(..., description="城市")
state: str = Field(..., description="州/省")
zip_code: str = Field(..., description="邮政编码")
created_at: str = Field(..., description="创建时间")
updated_at: str = Field(..., description="更新时间")
# 计算属性
full_name: str = Field(..., description="完整姓名")
full_address: str = Field(..., description="完整地址")
model_config = ConfigDict(from_attributes=True)
@classmethod
def from_orm(cls, obj):
"""Custom ORM conversion to handle datetime serialization"""
data = {}
for field in cls.model_fields:
value = getattr(obj, field, None)
if isinstance(value, datetime):
data[field] = value.isoformat()
else:
data[field] = value
# Add computed fields
if hasattr(obj, 'first_name') and hasattr(obj, 'last_name'):
data['full_name'] = f"{obj.first_name} {obj.last_name}".strip()
if hasattr(obj, 'street_address') and hasattr(obj, 'city') and hasattr(obj, 'state') and hasattr(obj, 'zip_code'):
data['full_address'] = f"{obj.street_address}, {obj.city}, {obj.state} {obj.zip_code}".strip(", ")
return cls(**data)
class UserDataStatsResponse(BaseModel):
"""用户数据统计响应模型"""
total_users: int = Field(..., description="总用户数")
total_orders: int = Field(..., description="总订单数")
recent_uploads: int = Field(..., description="最近上传数量")
success_rate: float = Field(..., description="成功率")