schema.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. import re
  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
  12. from app.core.validator import DateTimeStr
  13. class DictTypeCreateSchema(BaseModel):
  14. """
  15. 字典类型表对应pydantic模型
  16. """
  17. dict_name: str = Field(..., min_length=1, max_length=64, description="字典名称")
  18. dict_type: str = Field(..., min_length=1, max_length=64, description="字典类型")
  19. status: str = Field(default="0", description="状态(0正常 1停用)")
  20. description: str | None = Field(default=None, max_length=255, description="描述")
  21. @field_validator("dict_name")
  22. def validate_dict_name(cls, value: str):
  23. """
  24. 校验字典名称为非空字符串。
  25. 参数:
  26. - value (str): 字典名称。
  27. 返回:
  28. - str: 去首尾空格后的字典名称。
  29. 异常:
  30. - ValueError: 字典名称为空时抛出。
  31. """
  32. if not value or value.strip() == "":
  33. raise ValueError("字典名称不能为空")
  34. return value.strip()
  35. @field_validator("dict_type")
  36. def validate_dict_type(cls, value: str):
  37. """
  38. 校验字典类型:小写字母开头,仅包含小写字母/数字/下划线。
  39. 参数:
  40. - value (str): 字典类型。
  41. 返回:
  42. - str: 去首尾空格后的字典类型。
  43. 异常:
  44. - ValueError: 字典类型为空或不满足格式要求时抛出。
  45. """
  46. if not value or value.strip() == "":
  47. raise ValueError("字典类型不能为空")
  48. regexp = r"^[a-z][a-z0-9_]*$"
  49. if not re.match(regexp, value):
  50. raise ValueError("字典类型必须以字母开头,且只能为(小写字母,数字,下滑线)")
  51. return value.strip()
  52. class DictTypeUpdateSchema(DictTypeCreateSchema):
  53. """字典类型更新模型"""
  54. class DictTypeOutSchema(DictTypeCreateSchema, BaseSchema):
  55. """字典类型响应模型"""
  56. model_config = ConfigDict(from_attributes=True)
  57. class DictTypeQueryParam:
  58. """字典类型查询参数"""
  59. def __init__(
  60. self,
  61. dict_name: str | None = Query(default=None, description="字典名称", max_length=100),
  62. dict_type: str | None = Query(default=None, description="字典类型", max_length=100),
  63. status: str | None = Query(default=None, description="状态(0正常 1停用)"),
  64. created_time: list[DateTimeStr] | None = Query(
  65. None,
  66. description="创建时间范围",
  67. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  68. ),
  69. updated_time: list[DateTimeStr] | None = Query(
  70. None,
  71. description="更新时间范围",
  72. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  73. ),
  74. ) -> None:
  75. super().__init__()
  76. # 模糊查询字段
  77. self.dict_name = (QueueEnum.like.value, dict_name)
  78. # 精确查询字段
  79. self.dict_type = (QueueEnum.eq.value, dict_type)
  80. self.status = (QueueEnum.eq.value, status)
  81. # 时间范围查询
  82. if created_time and len(created_time) == 2:
  83. self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
  84. if updated_time and len(updated_time) == 2:
  85. self.updated_time = (QueueEnum.between.value, (updated_time[0], updated_time[1]))
  86. class DictDataCreateSchema(BaseModel):
  87. """
  88. 字典数据表对应pydantic模型
  89. """
  90. dict_sort: int = Field(..., ge=1, le=999, description="字典排序")
  91. dict_label: str = Field(..., max_length=100, description="字典标签")
  92. dict_value: str = Field(..., max_length=100, description="字典键值")
  93. dict_type: str = Field(..., max_length=100, description="字典类型")
  94. dict_type_id: int = Field(..., description="字典类型ID")
  95. css_class: str | None = Field(
  96. default=None, max_length=100, description="样式属性(其他样式扩展)"
  97. )
  98. list_class: str | None = Field(default=None, description="表格回显样式")
  99. is_default: bool = Field(default=False, description="是否默认(True是 False否)")
  100. status: str = Field(default="0", description="状态(0正常 1停用)")
  101. description: str | None = Field(default=None, max_length=255, description="描述")
  102. @model_validator(mode="after")
  103. def validate_after(self):
  104. """
  105. 校验并规范化字典数据字段(标签/键值/类型/类型ID)。
  106. 返回:
  107. - DictDataCreateSchema: 校验与去空格后的同一实例。
  108. 异常:
  109. - ValueError: 必填字段为空或类型ID非法时抛出。
  110. """
  111. if not self.dict_label or not self.dict_label.strip():
  112. raise ValueError("字典标签不能为空")
  113. if not self.dict_value or not self.dict_value.strip():
  114. raise ValueError("字典键值不能为空")
  115. if not self.dict_type or not self.dict_type.strip():
  116. raise ValueError("字典类型不能为空")
  117. if not hasattr(self, "dict_type_id") or self.dict_type_id <= 0:
  118. raise ValueError("字典类型ID不能为空且必须大于0")
  119. # 确保字符串字段被正确处理
  120. self.dict_label = self.dict_label.strip()
  121. self.dict_value = self.dict_value.strip()
  122. self.dict_type = self.dict_type.strip()
  123. return self
  124. class DictDataUpdateSchema(DictDataCreateSchema):
  125. """字典数据更新模型"""
  126. class DictDataOutSchema(DictDataCreateSchema, BaseSchema):
  127. """字典数据响应模型"""
  128. model_config = ConfigDict(from_attributes=True)
  129. class DictDataQueryParam:
  130. """字典数据查询参数"""
  131. def __init__(
  132. self,
  133. dict_label: str | None = Query(default=None, description="字典标签", max_length=100),
  134. dict_type: str | None = Query(default=None, description="字典类型", max_length=100),
  135. dict_type_id: int | None = Query(default=None, description="字典类型ID"),
  136. status: str | None = Query(default=None, description="状态(0正常 1停用)"),
  137. created_time: list[DateTimeStr] | None = Query(
  138. default=None,
  139. description="创建时间范围",
  140. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  141. ),
  142. updated_time: list[DateTimeStr] | None = Query(
  143. default=None,
  144. description="更新时间范围",
  145. examples=["2025-01-01 00:00:00", "2025-12-31 23:59:59"],
  146. ),
  147. ) -> None:
  148. # 模糊查询字段
  149. self.dict_label = (QueueEnum.like.value, dict_label)
  150. # 精确查询字段
  151. self.dict_type = (QueueEnum.eq.value, dict_type)
  152. self.dict_type_id = (QueueEnum.eq.value, dict_type_id)
  153. self.status = (QueueEnum.eq.value, status)
  154. # 时间范围查询
  155. if created_time and len(created_time) == 2:
  156. self.created_time = (QueueEnum.between.value, (created_time[0], created_time[1]))
  157. if updated_time and len(updated_time) == 2:
  158. self.updated_time = (QueueEnum.between.value, (updated_time[0], updated_time[1]))