schema.py 3.7 KB

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