schema.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. from pydantic import BaseModel, ConfigDict, Field, model_validator
  2. from pydantic.alias_generators import to_camel
  3. class ImportFieldModel(BaseModel):
  4. """
  5. Excel 导入时单字段映射配置(数据库列、Excel 列、默认值、是否必选等)。
  6. """
  7. model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
  8. base_column: str | None = Field(description="数据库字段名", default=None)
  9. excel_column: str | None = Field(description="excel字段名", default=None)
  10. default_value: str | None = Field(description="默认值", default=None)
  11. is_required: bool | None = Field(description="是否必传", default=None)
  12. selected: bool | None = Field(description="是否勾选", default=None)
  13. @model_validator(mode="before")
  14. @classmethod
  15. def _normalize(cls, data):
  16. if isinstance(data, dict):
  17. for key in ("base_column", "excel_column", "default_value"):
  18. val = data.get(key)
  19. if isinstance(val, str):
  20. val = val.strip()
  21. if val == "":
  22. val = None
  23. data[key] = val
  24. # is_required 兼容转换
  25. val = data.get("is_required")
  26. if isinstance(val, str):
  27. lowered = val.strip().lower()
  28. if lowered in {"true", "1", "y", "yes"}:
  29. data["is_required"] = True
  30. elif lowered in {"false", "0", "n", "no"}:
  31. data["is_required"] = False
  32. return data
  33. @model_validator(mode="after")
  34. def _validate(self):
  35. if self.selected and not (self.base_column and self.base_column.strip()):
  36. raise ValueError("选中字段必须提供数据库字段名")
  37. if self.is_required and not (self.excel_column and self.excel_column.strip()):
  38. raise ValueError("必传字段必须提供excel字段名")
  39. return self
  40. class ImportModel(BaseModel):
  41. """
  42. Excel 导入请求体:目标表、Sheet、文件名及字段映射列表。
  43. """
  44. model_config = ConfigDict(alias_generator=to_camel, from_attributes=True)
  45. table_name: str | None = Field(description="表名", default=None)
  46. sheet_name: str | None = Field(description="Sheet名", default=None)
  47. filed_info: list[ImportFieldModel] | None = Field(description="字段关联表", default=None)
  48. file_name: str | None = Field(description="文件名", default=None)
  49. @model_validator(mode="after")
  50. def _validate(self):
  51. # excel_column 不重复(忽略 None)
  52. if self.filed_info:
  53. seen = set()
  54. for f in self.filed_info:
  55. if f.excel_column:
  56. key = f.excel_column.strip()
  57. if key in seen:
  58. raise ValueError("excel字段名存在重复")
  59. seen.add(key)
  60. return self