base.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. """CRUD基础类"""
  2. from typing import TypeVar, Generic, Type, Optional, List, Any
  3. from sqlalchemy.orm import Session
  4. from sqlalchemy import and_, or_
  5. import re
  6. from app.core.utils import generate_id
  7. from app.core.database import Base
  8. from sqlalchemy import func
  9. ModelType = TypeVar("ModelType", bound=Base)
  10. def camel_to_snake(name: str) -> str:
  11. """驼峰命名转蛇形命名"""
  12. s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
  13. return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()
  14. def get_model_attr(obj, key: str):
  15. """获取模型的属性名,支持驼峰转蛇形"""
  16. # 先尝试直接匹配
  17. if hasattr(obj, key):
  18. return key
  19. # 尝试驼峰转蛇形
  20. snake_key = camel_to_snake(key)
  21. if hasattr(obj, snake_key):
  22. return snake_key
  23. # 如果都没有,返回None
  24. return None
  25. class CRUDBase(Generic[ModelType]):
  26. """CRUD基类"""
  27. def __init__(self, model: Type[ModelType]):
  28. self.model = model
  29. def get(self, db: Session, id: str) -> Optional[ModelType]:
  30. """根据ID获取单条记录"""
  31. return db.query(self.model).filter(self.model.id == id).first()
  32. def get_multi(
  33. self,
  34. db: Session,
  35. skip: int = 0,
  36. limit: int = 100,
  37. filters: List[Any] = None,
  38. order_by: str = None,
  39. order_type: str = "desc"
  40. ) -> List[ModelType]:
  41. """获取多条记录"""
  42. query = db.query(self.model)
  43. if filters:
  44. query = query.filter(*filters)
  45. if order_by:
  46. order_column = getattr(self.model, order_by, None)
  47. if order_column:
  48. if order_type == "asc":
  49. query = query.order_by(order_column.asc())
  50. else:
  51. query = query.order_by(order_column.desc())
  52. else:
  53. query = query.order_by(self.model.create_at.desc())
  54. return query.offset(skip).limit(limit).all()
  55. def get_all(self, db: Session, filters: List[Any] = None) -> List[ModelType]:
  56. """获取所有记录"""
  57. query = db.query(self.model)
  58. if filters:
  59. query = query.filter(*filters)
  60. return query.all()
  61. def create(self, db: Session, obj_in: dict, creator: dict = None) -> ModelType:
  62. """创建记录"""
  63. obj = self.model()
  64. for key, value in obj_in.items():
  65. attr_name = get_model_attr(obj, key)
  66. if attr_name:
  67. setattr(obj, attr_name, value)
  68. # 设置ID
  69. if not obj.id:
  70. obj.id = generate_id()
  71. # 设置创建人信息
  72. if creator:
  73. if not obj.create_by and "user_id" in creator:
  74. obj.create_by = creator["user_id"]
  75. if not obj.create_name and "real_name" in creator:
  76. obj.create_name = creator["real_name"]
  77. db.add(obj)
  78. db.commit()
  79. db.refresh(obj)
  80. return obj
  81. def update(self, db: Session, id: str, obj_in: dict, updater: dict = None) -> Optional[ModelType]:
  82. """更新记录"""
  83. obj = self.get(db, id)
  84. if obj:
  85. for key, value in obj_in.items():
  86. attr_name = get_model_attr(obj, key)
  87. if attr_name and key not in ["id", "create_at", "create_by", "create_name"]:
  88. setattr(obj, attr_name, value)
  89. # 设置更新人信息
  90. if updater:
  91. if "user_id" in updater:
  92. obj.update_by = updater["user_id"]
  93. if "real_name" in updater:
  94. obj.update_name = updater.get("real_name", obj.create_name)
  95. obj.update_at = func.now()
  96. db.commit()
  97. db.refresh(obj)
  98. return obj
  99. def delete(self, db: Session, id: str) -> bool:
  100. """删除记录(软删除)"""
  101. obj = self.get(db, id)
  102. if obj:
  103. if hasattr(obj, "is_del"):
  104. obj.is_del = 1
  105. else:
  106. db.delete(obj)
  107. db.commit()
  108. return True
  109. return False
  110. def hard_delete(self, db: Session, id: str) -> bool:
  111. """物理删除"""
  112. obj = self.get(db, id)
  113. if obj:
  114. db.delete(obj)
  115. db.commit()
  116. return True
  117. return False
  118. def count(self, db: Session, filters: List[Any] = None) -> int:
  119. """统计数量"""
  120. query = db.query(self.model)
  121. if filters:
  122. query = query.filter(*filters)
  123. return query.count()
  124. def exists(self, db: Session, filters: List[Any] = None) -> bool:
  125. """检查记录是否存在"""
  126. query = db.query(self.model)
  127. if filters:
  128. query = query.filter(*filters)
  129. return query.first() is not None
  130. class HistoryCRUD(CRUDBase[ModelType]):
  131. """历史表CRUD类"""
  132. def create_history(self, db: Session, original_data: dict) -> ModelType:
  133. """创建历史记录"""
  134. obj = self.model()
  135. # 复制原始数据到历史表
  136. for key, value in original_data.items():
  137. if hasattr(obj, key):
  138. setattr(obj, key, value)
  139. # 设置历史记录创建时间
  140. if hasattr(obj, "his_create_at"):
  141. obj.his_create_at = func.now()
  142. db.add(obj)
  143. db.commit()
  144. db.refresh(obj)
  145. return obj