mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 04:46:26 +00:00
refactor(module_generator): 重构代码生成模块结构
重构代码生成模块,删除冗余文件并优化结构: 1. 删除旧的form、page、table等相关文件 2. 新增gencode模块基础结构 3. 移动jinja2工具类和模板引擎初始化器到utils目录 4. 优化数据库模型关系定义 5. 更新nginx配置支持WebSocket 6. 添加正则验证和加密工具类 7. 修复菜单和部门模型的循环引用问题 8. 优化初始化脚本和配置加载逻辑 调整初始化流程,使用统一会话管理: 1. 修改数据库初始化使用AsyncSessionLocal 2. 优化定时任务初始化逻辑 3. 统一配置和字典服务初始化方式 4. 修复模型关系定义导致的循环导入问题 其他改进: 1. 更新requirements.txt添加依赖 2. 调整IP白名单配置 3. 优化数据库连接日志输出 4. 修复模型继承关系问题
This commit is contained in:
@@ -9,6 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from redis.asyncio.client import Redis
|
||||
|
||||
from app.common.enums import RedisInitKeyConfig
|
||||
from app.core.database import AsyncSessionLocal
|
||||
from app.core.redis_crud import RedisCURD
|
||||
from app.utils.excel_util import ExcelUtil
|
||||
from app.utils.upload_util import UploadUtil
|
||||
@@ -158,27 +159,28 @@ class ConfigService:
|
||||
).model_dump()
|
||||
|
||||
@classmethod
|
||||
async def init_config_service(cls, redis: Redis, db: AsyncSession) -> bool:
|
||||
auth = AuthSchema(db=db)
|
||||
config_obj = await ConfigCRUD(auth).get_obj_list_crud()
|
||||
if not config_obj:
|
||||
raise CustomException(msg="系统配置不存在")
|
||||
try:
|
||||
# 保存到Redis并设置过期时间
|
||||
for config in config_obj:
|
||||
redis_key = (f"{RedisInitKeyConfig.SYSTEM_CONFIG.key}:{config.config_key}")
|
||||
config_obj_dict = ConfigOutSchema.model_validate(config).model_dump()
|
||||
value = json.dumps(config_obj_dict, ensure_ascii=False)
|
||||
result = await RedisCURD(redis).set(
|
||||
key=redis_key,
|
||||
value=value,
|
||||
)
|
||||
if not result:
|
||||
logger.error(f"初始化系统配置失败: {config_obj_dict}")
|
||||
raise CustomException(msg="初始化系统配置失败")
|
||||
except Exception as e:
|
||||
logger.error(f"初始化系统配置失败: {e}")
|
||||
raise CustomException(msg="初始化系统配置失败")
|
||||
async def init_config_service(cls, redis: Redis) -> bool:
|
||||
async with AsyncSessionLocal() as session:
|
||||
auth = AuthSchema(db=session)
|
||||
config_obj = await ConfigCRUD(auth).get_obj_list_crud()
|
||||
if not config_obj:
|
||||
raise CustomException(msg="系统配置不存在")
|
||||
try:
|
||||
# 保存到Redis并设置过期时间
|
||||
for config in config_obj:
|
||||
redis_key = (f"{RedisInitKeyConfig.SYSTEM_CONFIG.key}:{config.config_key}")
|
||||
config_obj_dict = ConfigOutSchema.model_validate(config).model_dump()
|
||||
value = json.dumps(config_obj_dict, ensure_ascii=False)
|
||||
result = await RedisCURD(redis).set(
|
||||
key=redis_key,
|
||||
value=value,
|
||||
)
|
||||
if not result:
|
||||
logger.error(f"初始化系统配置失败: {config_obj_dict}")
|
||||
raise CustomException(msg="初始化系统配置失败")
|
||||
except Exception as e:
|
||||
logger.error(f"初始化系统配置失败: {e}")
|
||||
raise CustomException(msg="初始化系统配置失败")
|
||||
|
||||
@classmethod
|
||||
async def get_init_config_service(cls, redis: Redis) -> Dict:
|
||||
|
||||
@@ -17,9 +17,12 @@ class DeptModel(ModelMixin):
|
||||
name: Mapped[str] = mapped_column(String(40),nullable=False,unique=True,comment="部门名称")
|
||||
order: Mapped[int] = mapped_column(Integer,nullable=False,default=999,comment="显示排序")
|
||||
|
||||
parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("system_dept.id", ondelete="CASCADE", onupdate="CASCADE"), nullable=True, index=True, comment="父级部门ID")
|
||||
parent: Mapped[Optional["DeptModel"]] = relationship("DeptModel", cascade="all, delete-orphan", uselist=False)
|
||||
parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey("system_dept.id", ondelete="SET NULL", onupdate="CASCADE"), default=None, index=True, comment="父级部门ID")
|
||||
# parent: Mapped[Optional["DeptModel"]] = relationship("DeptModel", cascade="all, delete-orphan", uselist=False)
|
||||
|
||||
parent: Mapped[Optional['DeptModel']] = relationship(init=False, back_populates='children', remote_side=[id])
|
||||
children: Mapped[Optional[list['DeptModel']]] = relationship(init=False, back_populates='parent')
|
||||
|
||||
# 角色关联关系
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_depts", back_populates="depts", lazy="selectin")
|
||||
|
||||
@@ -27,6 +30,4 @@ class DeptModel(ModelMixin):
|
||||
users: Mapped[List["UserModel"]] = relationship(back_populates="dept", lazy="selectin")
|
||||
|
||||
# code: Mapped[Optional[str]] = mapped_column(String(20),nullable=True,unique=True,comment="部门编码")
|
||||
# leader_id: Mapped[Optional[int]] = mapped_column(Integer,nullable=True,comment="负责人ID")
|
||||
# parent: Mapped[Optional["DeptModel"]] = relationship(back_populates="children",remote_side=[id],lazy="select",uselist=False,foreign_keys=[parent_id])
|
||||
# children: Mapped[List["DeptModel"]] = relationship(back_populates="parent",lazy="select",cascade="all, delete-orphan",foreign_keys=[parent_id])
|
||||
# leader_id: Mapped[Optional[int]] = mapped_column(Integer,nullable=True,comment="负责人ID")
|
||||
@@ -7,6 +7,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.common.enums import RedisInitKeyConfig
|
||||
from app.utils.excel_util import ExcelUtil
|
||||
from app.core.database import AsyncSessionLocal
|
||||
from app.core.base_schema import BatchSetAvailable
|
||||
from app.core.redis_crud import RedisCURD
|
||||
from app.core.exceptions import CustomException
|
||||
@@ -187,33 +188,33 @@ class DictDataService:
|
||||
@classmethod
|
||||
async def init_dict_service(cls, redis: Redis, db: AsyncSession):
|
||||
"""应用初始化: 获取所有字典类型对应的字典数据信息并缓存service"""
|
||||
|
||||
auth = AuthSchema(db=db)
|
||||
obj_list = await DictTypeCRUD(auth).get_obj_list_crud()
|
||||
if not obj_list:
|
||||
logger.warning("未找到任何字典类型数据")
|
||||
return
|
||||
for obj in obj_list:
|
||||
dict_type = obj.dict_type
|
||||
dict_data_list = await DictDataCRUD(auth).get_obj_list_crud(search={'dict_type': dict_type})
|
||||
|
||||
if not dict_data_list:
|
||||
logger.warning(f"字典类型 {dict_type} 未找到对应的字典数据")
|
||||
continue
|
||||
|
||||
dict_data = [DictDataOutSchema.model_validate(row).model_dump() for row in dict_data_list if row]
|
||||
|
||||
# 保存到Redis并设置过期时间
|
||||
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{dict_type}"
|
||||
try:
|
||||
value = json.dumps(dict_data, ensure_ascii=False)
|
||||
await RedisCURD(redis).set(
|
||||
key=redis_key,
|
||||
value=value,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"初始化字典数据失败: {e}")
|
||||
raise CustomException(msg=f"初始化字典数据失败 {e}")
|
||||
async with AsyncSessionLocal() as session:
|
||||
auth = AuthSchema(db=session)
|
||||
obj_list = await DictTypeCRUD(auth).get_obj_list_crud()
|
||||
if not obj_list:
|
||||
logger.warning("未找到任何字典类型数据")
|
||||
return
|
||||
for obj in obj_list:
|
||||
dict_type = obj.dict_type
|
||||
dict_data_list = await DictDataCRUD(auth).get_obj_list_crud(search={'dict_type': dict_type})
|
||||
|
||||
if not dict_data_list:
|
||||
logger.warning(f"字典类型 {dict_type} 未找到对应的字典数据")
|
||||
continue
|
||||
|
||||
dict_data = [DictDataOutSchema.model_validate(row).model_dump() for row in dict_data_list if row]
|
||||
|
||||
# 保存到Redis并设置过期时间
|
||||
redis_key = f"{RedisInitKeyConfig.SYSTEM_DICT.key}:{dict_type}"
|
||||
try:
|
||||
value = json.dumps(dict_data, ensure_ascii=False)
|
||||
await RedisCURD(redis).set(
|
||||
key=redis_key,
|
||||
value=value,
|
||||
)
|
||||
except Exception as e:
|
||||
logger.error(f"初始化字典数据失败: {e}")
|
||||
raise CustomException(msg=f"初始化字典数据失败 {e}")
|
||||
|
||||
@classmethod
|
||||
async def get_init_dict_service(cls, redis: Redis, dict_type: str)->List[Dict]:
|
||||
|
||||
@@ -42,12 +42,12 @@ class MenuModel(ModelMixin):
|
||||
affix: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, comment='是否固定标签页(True:是 False:否)')
|
||||
|
||||
parent_id: Mapped[Optional[int]] = mapped_column(Integer, ForeignKey('system_menu.id', ondelete='SET NULL'), default=None, index=True, comment='父菜单ID')
|
||||
parent: Mapped[Optional['MenuModel']] = relationship(cascade='all, delete-orphan', primaryjoin="MenuModel.parent_id == MenuModel.id", uselist=False)
|
||||
# parent: Mapped[Optional['MenuModel']] = relationship(cascade='all, delete-orphan', primaryjoin="MenuModel.parent_id == MenuModel.id", uselist=False)
|
||||
|
||||
# 角色关联关系
|
||||
roles: Mapped[List["RoleModel"]] = relationship(secondary="system_role_menus", back_populates="menus", lazy="selectin")
|
||||
|
||||
# link: Mapped[Optional[str]] = mapped_column(String(255), comment='外链地址')
|
||||
# iframe: Mapped[Optional[str]] = mapped_column(String(255), comment='内嵌iframe地址')
|
||||
# parent: Mapped[Optional['MenuModel']] = relationship(init=False, back_populates='children', remote_side=[id])
|
||||
# children: Mapped[Optional[list['MenuModel']]] = relationship(init=False, back_populates='parent')
|
||||
parent: Mapped[Optional['MenuModel']] = relationship(init=False, back_populates='children', remote_side=[id])
|
||||
children: Mapped[Optional[list['MenuModel']]] = relationship(init=False, back_populates='parent')
|
||||
|
||||
Reference in New Issue
Block a user