代码提交
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
"""Pydantic 公共模型与校验小工具。"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date, datetime
|
||||
from enum import Enum
|
||||
from typing import Any, Generic, TypeVar
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
from app.model.constants import gender_to_code
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
||||
class ORMBase(BaseModel):
|
||||
"""所有出参模型的基类:允许直接吃 ORM 对象(含 @property 派生字段)。"""
|
||||
|
||||
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
||||
|
||||
|
||||
class PageResult(BaseModel, Generic[T]):
|
||||
total: int = Field(0, description="总条数")
|
||||
page: int = Field(1, description="当前页")
|
||||
page_size: int = Field(10, description="每页条数")
|
||||
pages: int = Field(0, description="总页数")
|
||||
items: list[T] = Field(default_factory=list, description="数据列表")
|
||||
|
||||
|
||||
class SortOrder(str, Enum):
|
||||
ASC = "asc"
|
||||
DESC = "desc"
|
||||
|
||||
|
||||
class DateRangeMixin(BaseModel):
|
||||
start_date: str | None = Field(None, description="起始日期 YYYY-MM-DD")
|
||||
end_date: str | None = Field(None, description="结束日期 YYYY-MM-DD")
|
||||
|
||||
|
||||
# ---------------------------------------------------------------- 校验器
|
||||
def _normalize_gender(cls, v): # noqa: ANN001, ANN201
|
||||
if v is None:
|
||||
return v
|
||||
code = gender_to_code(v)
|
||||
if code is None:
|
||||
raise ValueError("性别只能是 1/2 或 男/女")
|
||||
return code
|
||||
|
||||
|
||||
def _strip_str(cls, v): # noqa: ANN001, ANN201
|
||||
return v.strip() if isinstance(v, str) else v
|
||||
|
||||
|
||||
GENDER_VALIDATOR = field_validator("gender", mode="before", check_fields=False)(_normalize_gender)
|
||||
STRIP_VALIDATOR = field_validator("*", mode="before", check_fields=False)(_strip_str)
|
||||
|
||||
|
||||
def date_to_str(value: date | datetime | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, datetime):
|
||||
return value.date().isoformat()
|
||||
return value.isoformat()
|
||||
|
||||
|
||||
def as_dict(model: Any) -> dict:
|
||||
return model.model_dump(exclude_unset=True)
|
||||
Reference in New Issue
Block a user