schema.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. from dataclasses import dataclass
  2. from fastapi import Query
  3. from pydantic import (
  4. BaseModel,
  5. ConfigDict,
  6. Field,
  7. field_validator,
  8. model_validator,
  9. )
  10. from app.common.enums import QueueEnum
  11. from app.core.base_schema import BaseSchema, UserBySchema
  12. from app.core.validator import DateStr, DateTimeStr, TimeStr
  13. class DemoCreateSchema(BaseModel):
  14. """新增模型"""
  15. name: str = Field(..., description="名称")
  16. status: str = Field(default="0", description="是否启用(0:启用 1:禁用)")
  17. description: str | None = Field(default=None, description="描述")
  18. a: int | None = Field(default=None, description="整数")
  19. b: int | None = Field(default=None, description="大整数")
  20. c: float | None = Field(default=None, description="浮点数")
  21. d: bool = Field(default=True, description="布尔型")
  22. e: DateStr | None = Field(default=None, description="日期")
  23. f: TimeStr | None = Field(default=None, description="时间")
  24. g: DateTimeStr | None = Field(default=None, description="日期时间")
  25. h: str | None = Field(default=None, description="长文本")
  26. i: dict | None = Field(default=None, description="元数据(JSON格式)")
  27. @field_validator("name")
  28. @classmethod
  29. def validate_name(cls, v: str) -> str:
  30. """
  31. 验证名称字段的格式和内容。
  32. 参数:
  33. - v (str): 原始名称。
  34. 返回:
  35. - str: 去空白后的名称。
  36. 异常:
  37. - ValueError: 名称为空时抛出。
  38. """
  39. # 去除首尾空格
  40. v = v.strip()
  41. if not v:
  42. raise ValueError("名称不能为空")
  43. return v
  44. @model_validator(mode="after")
  45. def _after_validation(self):
  46. """
  47. 核心业务规则校验
  48. """
  49. # 长度校验:名称最小长度
  50. if len(self.name) < 2 or len(self.name) > 50:
  51. raise ValueError("名称长度必须在2-50个字符之间")
  52. # 格式校验:名称只能包含字母、数字、下划线和中划线
  53. if not self.name.isalnum() and not all(c in "-_" for c in self.name):
  54. raise ValueError("名称只能包含字母、数字、下划线和中划线")
  55. if self.status not in ["0", "1"]:
  56. raise ValueError("是否启用必须为0或1")
  57. # 描述校验:描述最大长度
  58. if self.description and len(self.description) > 255:
  59. raise ValueError("描述长度不能超过255个字符")
  60. return self
  61. class DemoUpdateSchema(DemoCreateSchema):
  62. """更新模型"""
  63. class DemoOutSchema(DemoCreateSchema, BaseSchema, UserBySchema):
  64. """响应模型"""
  65. model_config = ConfigDict(from_attributes=True)
  66. @dataclass
  67. class DemoQueryParam:
  68. """示例查询参数"""
  69. def __init__(
  70. self,
  71. name: str | None = Query(None, description="名称"),
  72. description: str | None = Query(None, description="描述"),
  73. status: str | None = Query(None, description="是否启用"),
  74. created_time: list[DateTimeStr] | None = Query(
  75. None,
  76. description="创建时间范围",
  77. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  78. ),
  79. updated_time: list[DateTimeStr] | None = Query(
  80. None,
  81. description="更新时间范围",
  82. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  83. ),
  84. created_id: int | None = Query(None, description="创建人"),
  85. updated_id: int | None = Query(None, description="更新人"),
  86. ) -> None:
  87. # 模糊查询字段
  88. self.name = (QueueEnum.like.value, name)
  89. if description:
  90. self.description = (QueueEnum.like.value, description)
  91. # 精确查询字段
  92. if status:
  93. self.status = (QueueEnum.eq.value, status)
  94. # 时间范围查询
  95. if created_time and len(created_time) == 2:
  96. self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
  97. if updated_time and len(updated_time) == 2:
  98. self.updated_time = (QueueEnum.between.value, (updated_time[0], updated_time[1]))
  99. # 关联查询字段
  100. if created_id:
  101. self.created_id = (QueueEnum.eq.value, created_id)
  102. if updated_id:
  103. self.updated_id = (QueueEnum.eq.value, updated_id)