mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-20 20:39:55 +00:00
refactor(gencode): 重构代码生成模块,优化模板和查询逻辑
重构代码生成模块的模板文件,统一命名规范为下划线风格 优化GenTableQueryParam查询参数类,移除不必要的字段 修复SQLite数据库支持问题,改进表结构查询逻辑 添加数据验证处理,防止空值导致的异常 改进批量生成代码时的错误处理和参数校验
This commit is contained in:
@@ -10,6 +10,7 @@ from app.core.router_class import OperationLogRoute
|
||||
from app.core.base_params import PaginationQueryParam
|
||||
from app.common.request import PaginationService
|
||||
from app.api.v1.module_system.auth.schema import AuthSchema
|
||||
from app.common.constant import RET
|
||||
from .param import GenTableQueryParam
|
||||
from .schema import GenTableDeleteSchema, GenTableSchema, GenTableOutSchema
|
||||
from .service import GenTableColumnService, GenTableService
|
||||
@@ -62,14 +63,14 @@ async def gen_table_detail_controller(
|
||||
) -> JSONResponse:
|
||||
gen_table = await GenTableService.get_gen_table_by_id_service(auth, table_id)
|
||||
gen_tables = await GenTableService.get_gen_table_all_service(auth)
|
||||
gen_table_detail_result = dict(info=gen_table, rows=gen_table.columns, tables=gen_tables)
|
||||
gen_table_detail_result = dict(info=gen_table.model_dump(), rows=gen_table.model_dump()['columns'], tables=[gen_table.model_dump() for gen_table in gen_tables])
|
||||
logger.info(f'获取table_id为{table_id}的信息成功')
|
||||
return SuccessResponse(data=gen_table_detail_result, msg="获取业务表详细信息成功")
|
||||
|
||||
|
||||
@GenRouter.post("/create", summary="创建表结构", description="创建表结构")
|
||||
async def create_table_controller(
|
||||
sql: str = Query(..., description="SQL语句"),
|
||||
sql: str = Query(..., description="SQL语句:CREATE TABLE user_demo (\n id INTEGER NOT NULL PRIMARY KEY,\n username VARCHAR(64) NOT NULL UNIQUE,\n);"),
|
||||
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:create"])),
|
||||
) -> JSONResponse:
|
||||
result = await GenTableService.create_table_service(auth, sql)
|
||||
@@ -101,9 +102,19 @@ async def delete_gen_table_controller(
|
||||
|
||||
@GenRouter.patch("/batch/output", summary="批量生成代码", description="批量生成代码")
|
||||
async def batch_gen_code_controller(
|
||||
table_names: List[str] = Query(None, description="表名列表"),
|
||||
table_names: List[str] = Query(..., description="表名列表"),
|
||||
auth: AuthSchema = Depends(AuthPermission(["generator:gencode:operate"]))
|
||||
) -> StreamResponse:
|
||||
# 检查table_names是否为空
|
||||
if not table_names:
|
||||
logger.error('表名列表不能为空')
|
||||
# 返回一个空的StreamResponse,包含错误信息
|
||||
error_content = bytes(f'{RET.ERROR.msg}: 表名列表不能为空', 'utf-8')
|
||||
return StreamResponse(
|
||||
data=bytes2file_response(error_content),
|
||||
media_type='text/plain',
|
||||
headers={'Content-Disposition': 'attachment; filename=error.txt'}
|
||||
)
|
||||
batch_gen_code_result = await GenTableService.batch_gen_code_service(auth, table_names)
|
||||
logger.info('批量生成代码成功')
|
||||
return StreamResponse(
|
||||
|
||||
@@ -95,14 +95,16 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
:return: 代码生成业务表列表信息对象
|
||||
"""
|
||||
# 构建查询条件
|
||||
conditions = await self.__build_conditions(**search.__dict__) if search else []
|
||||
query = (
|
||||
select(GenTableModel)
|
||||
.options(selectinload(GenTableModel.columns))
|
||||
.where(*conditions)
|
||||
.order_by(GenTableModel.created_at.desc())
|
||||
.distinct()
|
||||
)
|
||||
query = select(GenTableModel).options(selectinload(GenTableModel.columns))
|
||||
|
||||
if search:
|
||||
# 手动构建查询条件
|
||||
if search.table_name and search.table_name[1]: # ('like', value)
|
||||
query = query.where(GenTableModel.table_name.like(f"%{search.table_name[1]}%"))
|
||||
if search.table_comment and search.table_comment[1]: # ('like', value)
|
||||
query = query.where(GenTableModel.table_comment.like(f"%{search.table_comment[1]}%"))
|
||||
|
||||
query = query.order_by(GenTableModel.created_at.desc()).distinct()
|
||||
|
||||
# 获取所有数据
|
||||
result = await self.db.execute(query)
|
||||
@@ -167,7 +169,6 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
text("table_catalog = (select current_database())"),
|
||||
text("is_insertable_into = 'YES'"),
|
||||
text("table_schema = 'public'"),
|
||||
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -189,31 +190,44 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
else:
|
||||
query_sql = (
|
||||
select(
|
||||
text(f"{settings.DATABASE_NAME} as database_name"),
|
||||
text("'' as database_name"), # SQLite没有数据库名概念,设为空字符串
|
||||
text("name as table_name"),
|
||||
text("type as table_type"),
|
||||
text("tbl_name as table_comment"),
|
||||
text("name as table_comment"), # SQLite中使用name作为表名和注释
|
||||
)
|
||||
.select_from(text("sqlite_master"))
|
||||
.where(
|
||||
and_(
|
||||
text("type = 'table'"),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
# 动态条件构造
|
||||
if search and search.table_name:
|
||||
query_sql = query_sql.where(
|
||||
text("lower(table_name) like lower(:table_name)")
|
||||
)
|
||||
if search and search.table_comment:
|
||||
query_sql = query_sql.where(
|
||||
text("lower(table_comment) like lower(:table_comment)")
|
||||
)
|
||||
params = {}
|
||||
if search and search.table_name and search.table_name[1]:
|
||||
if settings.DATABASE_TYPE == "sqlite":
|
||||
query_sql = query_sql.where(
|
||||
text("lower(name) like lower(:table_name)")
|
||||
)
|
||||
else:
|
||||
query_sql = query_sql.where(
|
||||
text("lower(table_name) like lower(:table_name)")
|
||||
)
|
||||
params['table_name'] = f"%{search.table_name[1]}%"
|
||||
if search and search.table_comment and search.table_comment[1]:
|
||||
if settings.DATABASE_TYPE == "sqlite":
|
||||
query_sql = query_sql.where(
|
||||
text("lower(name) like lower(:table_comment)")
|
||||
)
|
||||
else:
|
||||
query_sql = query_sql.where(
|
||||
text("lower(table_comment) like lower(:table_comment)")
|
||||
)
|
||||
params['table_comment'] = f"%{search.table_comment[1]}%"
|
||||
|
||||
# 执行查询
|
||||
all_data =(await self.db.execute(query_sql)).fetchall()
|
||||
# 执行查询并绑定参数
|
||||
all_data = (await self.db.execute(query_sql, params)).fetchall()
|
||||
|
||||
# 将Row对象转换为字典列表,解决JSON序列化问题
|
||||
dict_data = []
|
||||
@@ -250,7 +264,6 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
text("table_catalog = (select current_database())"),
|
||||
text("is_insertable_into = 'YES'"),
|
||||
text("table_schema = 'public'"),
|
||||
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -272,10 +285,10 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
else:
|
||||
query_sql = (
|
||||
select(
|
||||
text(f"{settings.DATABASE_NAME} as database_name"),
|
||||
text("'' as database_name"), # SQLite没有数据库名概念,设为空字符串
|
||||
text("name as table_name"),
|
||||
text("type as table_type"),
|
||||
text("tbl_name as table_comment"),
|
||||
text("name as table_comment"), # SQLite中使用name作为表名和注释
|
||||
)
|
||||
.select_from(text("sqlite_master"))
|
||||
.where(
|
||||
@@ -285,10 +298,25 @@ class GenTableCRUD(CRUDBase[GenTableModel, GenTableSchema, GenTableSchema]):
|
||||
)
|
||||
)
|
||||
|
||||
query_sql = query_sql.where(
|
||||
text(f"table_name in :{table_names}")
|
||||
)
|
||||
gen_db_table_list = (await self.db.execute(query_sql)).fetchall()
|
||||
# 修复SQL查询中的参数绑定问题
|
||||
if table_names:
|
||||
if settings.DATABASE_TYPE == "sqlite":
|
||||
# 对于SQLite,我们直接在SQL中使用表名,因为参数绑定有问题
|
||||
table_names_str = "','".join(table_names)
|
||||
query_sql = query_sql.where(
|
||||
text(f"name IN ('{table_names_str}')")
|
||||
)
|
||||
gen_db_table_list = (await self.db.execute(query_sql)).fetchall()
|
||||
else:
|
||||
# MySQL和PostgreSQL使用:table_names占位符
|
||||
query_sql = query_sql.where(
|
||||
text("table_name IN :table_names")
|
||||
)
|
||||
# 使用params方法正确绑定参数
|
||||
query_sql = query_sql.params(table_names=tuple(table_names))
|
||||
gen_db_table_list = (await self.db.execute(query_sql)).fetchall()
|
||||
else:
|
||||
gen_db_table_list = (await self.db.execute(query_sql)).fetchall()
|
||||
|
||||
# 将Row对象转换为字典列表,解决JSON序列化问题
|
||||
dict_data = []
|
||||
@@ -358,10 +386,9 @@ class GenTableColumnCRUD(CRUDBase[GenTableColumnModel, GenTableColumnSchema, Gen
|
||||
(CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS is_increment,
|
||||
column_type
|
||||
FROM
|
||||
information_schema.tables
|
||||
information_schema.columns
|
||||
WHERE
|
||||
table_catalog = (select current_database())
|
||||
AND is_insertable_into = 'YES'
|
||||
AND table_schema = 'public'
|
||||
AND table_name = :table_name
|
||||
"""
|
||||
@@ -373,29 +400,27 @@ class GenTableColumnCRUD(CRUDBase[GenTableColumnModel, GenTableColumnSchema, Gen
|
||||
(CASE WHEN column_key = 'PRI' THEN '1' ELSE '0' END) AS is_pk,
|
||||
ordinal_position AS sort,
|
||||
column_comment,
|
||||
(CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS is_increment,
|
||||
(CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' end) AS is_increment,
|
||||
column_type
|
||||
FROM
|
||||
information_schema.tables
|
||||
information_schema.columns
|
||||
WHERE
|
||||
table_schema = (SELECT DATABASE())
|
||||
AND table_name = :table_name
|
||||
"""
|
||||
else:
|
||||
query_sql = f"""
|
||||
# 修复SQLite查询语句,使用PRAGMA获取表结构信息
|
||||
query_sql = """
|
||||
SELECT
|
||||
column_name,
|
||||
(CASE WHEN (is_nullable = 'no' AND column_key != 'PRI') THEN '1' ELSE '0' END) AS is_required,
|
||||
(CASE WHEN column_key = 'PRI' THEN '1' ELSE '0' END) AS is_pk,
|
||||
ordinal_position AS sort,
|
||||
column_comment,
|
||||
(CASE WHEN extra = 'auto_increment' THEN '1' ELSE '0' END) AS is_increment,
|
||||
column_type
|
||||
name as column_name,
|
||||
(CASE WHEN (type != '' AND pk != 1) THEN '1' ELSE '0' END) AS is_required,
|
||||
(CASE WHEN pk = 1 THEN '1' ELSE '0' END) AS is_pk,
|
||||
cid AS sort,
|
||||
'' as column_comment,
|
||||
(CASE WHEN type LIKE '%AUTOINCREMENT%' THEN '1' ELSE '0' END) AS is_increment,
|
||||
type as column_type
|
||||
FROM
|
||||
sqlite_master
|
||||
WHERE
|
||||
type = 'table'
|
||||
AND name = :table_name
|
||||
pragma_table_info(:table_name)
|
||||
"""
|
||||
|
||||
query = text(query_sql).bindparams(table_name=table_name)
|
||||
@@ -403,18 +428,24 @@ class GenTableColumnCRUD(CRUDBase[GenTableColumnModel, GenTableColumnSchema, Gen
|
||||
await self.db.execute(query)
|
||||
).fetchall()
|
||||
|
||||
return [
|
||||
GenTableColumnOutSchema(
|
||||
column_name=row[0],
|
||||
is_required=row[1],
|
||||
is_pk=row[2],
|
||||
sort=row[3],
|
||||
column_comment=row[4],
|
||||
is_increment=row[5],
|
||||
column_type=row[6],
|
||||
)
|
||||
for row in gen_db_table_columns_raw
|
||||
]
|
||||
result = []
|
||||
for row in gen_db_table_columns_raw:
|
||||
# 构造字段信息字典
|
||||
column_dict = {
|
||||
"column_name": row[0],
|
||||
"is_required": row[1],
|
||||
"is_pk": row[2],
|
||||
"sort": row[3],
|
||||
"column_comment": row[4],
|
||||
"is_increment": row[5],
|
||||
"column_type": row[6]
|
||||
}
|
||||
|
||||
# 创建GenTableColumnOutSchema对象
|
||||
column_schema = GenTableColumnOutSchema(**column_dict)
|
||||
result.append(column_schema)
|
||||
|
||||
return result
|
||||
|
||||
async def list_gen_table_column_crud(self, search: Optional[Dict] = None, order_by: Optional[List[Dict[str, str]]] = None) -> Sequence[GenTableColumnModel]:
|
||||
"""根据业务表ID查询业务表字段列表"""
|
||||
@@ -430,7 +461,14 @@ class GenTableColumnCRUD(CRUDBase[GenTableColumnModel, GenTableColumnSchema, Gen
|
||||
|
||||
async def delete_gen_table_column_by_table_id_dao(self, data: GenTableDeleteSchema) -> None:
|
||||
"""根据业务表ID批量删除"""
|
||||
return await self.delete(ids=data.table_ids)
|
||||
# 先查询出这些表ID对应的所有字段ID
|
||||
query = select(GenTableColumnModel.id).where(GenTableColumnModel.table_id.in_(data.table_ids))
|
||||
result = await self.db.execute(query)
|
||||
column_ids = [row[0] for row in result.fetchall()]
|
||||
|
||||
# 如果有字段ID,则删除这些字段
|
||||
if column_ids:
|
||||
await self.delete(ids=column_ids)
|
||||
|
||||
async def delete_gen_table_column_by_column_id_dao(self, data: GenTableColumnDeleteSchema) -> None:
|
||||
"""根据业务表字段ID批量删除"""
|
||||
|
||||
@@ -13,21 +13,11 @@ class GenTableQueryParam:
|
||||
self,
|
||||
table_name: Optional[str] = Query(None, description="表名称"),
|
||||
table_comment: Optional[str] = Query(None, description="表注释"),
|
||||
creator: Optional[int] = Query(None, description="创建人"),
|
||||
start_time: Optional[DateTimeStr] = Query(None, description="开始时间", example="2025-01-01 00:00:00"),
|
||||
end_time: Optional[DateTimeStr] = Query(None, description="结束时间", example="2025-12-31 23:59:59"),
|
||||
) -> None:
|
||||
# 模糊查询字段
|
||||
self.table_name = ("like", table_name)
|
||||
self.table_comment = ("like", table_comment)
|
||||
|
||||
# 精确查询字段
|
||||
self.creator_id = creator
|
||||
|
||||
# 时间范围查询
|
||||
if start_time and end_time:
|
||||
self.created_at = ("between", (start_time, end_time))
|
||||
|
||||
|
||||
class GenTableColumnQueryParam:
|
||||
"""代码生成业务表字段查询参数"""
|
||||
|
||||
@@ -82,6 +82,30 @@ class GenTableSchema(GenTableBaseSchema):
|
||||
|
||||
class GenTableOutSchema(GenTableSchema, BaseSchema):
|
||||
model_config = ConfigDict(from_attributes=True)
|
||||
|
||||
# 添加数据验证和转换的root_validator
|
||||
@model_validator(mode='before')
|
||||
def handle_null_values(cls, values):
|
||||
# 处理None值,转换为空字符串或适当的默认值
|
||||
# 检查values是否为对象而非字典
|
||||
if hasattr(values, '__dict__'):
|
||||
# 如果是对象,获取其字典表示
|
||||
values_dict = values.__dict__
|
||||
for key in ['table_name', 'table_comment', 'class_name', 'columns']:
|
||||
if key in values_dict and values_dict[key] is None:
|
||||
if key != 'columns':
|
||||
setattr(values, key, '')
|
||||
else:
|
||||
setattr(values, key, [])
|
||||
return values
|
||||
elif isinstance(values, dict):
|
||||
# 如果是字典,执行原来的逻辑
|
||||
for key, value in values.items():
|
||||
if value is None:
|
||||
if key in ['table_name', 'table_comment', 'class_name', 'columns']:
|
||||
values[key] = '' if key != 'columns' else []
|
||||
return values
|
||||
return values
|
||||
|
||||
|
||||
class GenTableDeleteSchema(BaseModel):
|
||||
|
||||
@@ -55,13 +55,51 @@ class GenTableService:
|
||||
async def get_gen_db_table_list_by_name_service(cls, auth: AuthSchema, table_names: List[str]) -> List[GenTableOutSchema]:
|
||||
"""根据表名称组获取数据库列表信息"""
|
||||
gen_db_table_list_result = await GenTableCRUD(auth=auth).get_db_table_list_by_names(table_names)
|
||||
return [GenTableOutSchema(**gen_table) for gen_table in CamelCaseUtil.transform_result(gen_db_table_list_result)]
|
||||
# 修复:将GenDBTableSchema对象转换为字典后再传递给GenTableOutSchema
|
||||
result = []
|
||||
for gen_table in CamelCaseUtil.transform_result(gen_db_table_list_result):
|
||||
# 确保gen_table是字典类型
|
||||
if hasattr(gen_table, 'model_dump'):
|
||||
gen_table_dict = gen_table.model_dump()
|
||||
elif isinstance(gen_table, dict):
|
||||
gen_table_dict = gen_table
|
||||
else:
|
||||
gen_table_dict = gen_table.__dict__
|
||||
result.append(GenTableOutSchema(**gen_table_dict))
|
||||
|
||||
# 检查是否有未找到的表
|
||||
found_table_names = [table.table_name for table in result]
|
||||
missing_tables = [name for name in table_names if name not in found_table_names]
|
||||
if missing_tables:
|
||||
raise CustomException(msg=f"以下数据表不存在: {', '.join(missing_tables)}")
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
async def import_gen_table_service(
|
||||
cls, auth: AuthSchema, gen_table_list: List[GenTableOutSchema]
|
||||
) -> Literal[True] | None:
|
||||
"""导入表结构"""
|
||||
# 检查是否有表需要导入
|
||||
if not gen_table_list:
|
||||
raise CustomException(msg="没有可导入的表结构")
|
||||
|
||||
# 检查表是否已存在
|
||||
existing_tables = []
|
||||
for table in gen_table_list:
|
||||
table_name = table.table_name
|
||||
# 确保table_name不为None
|
||||
if table_name is None:
|
||||
raise CustomException(msg="表名不能为空")
|
||||
# 检查表是否已存在
|
||||
existing_table = await GenTableCRUD(auth).get_gen_table_by_name(table_name)
|
||||
if existing_table:
|
||||
existing_tables.append(table_name)
|
||||
|
||||
# 如果有已存在的表,抛出异常
|
||||
if existing_tables:
|
||||
raise CustomException(msg=f"以下表已存在,不能重复导入: {', '.join(existing_tables)}")
|
||||
|
||||
try:
|
||||
for table in gen_table_list:
|
||||
table_name = table.table_name
|
||||
@@ -69,14 +107,27 @@ class GenTableService:
|
||||
add_gen_table = await GenTableCRUD(auth).add_gen_table(table)
|
||||
if add_gen_table:
|
||||
table.table_id = add_gen_table.id
|
||||
# 获取数据库表的字段信息
|
||||
gen_table_columns = await GenTableColumnCRUD(auth).get_gen_db_table_columns_by_name(table_name)
|
||||
for column in [
|
||||
GenTableColumnSchema(**gen_table_column)
|
||||
for gen_table_column in CamelCaseUtil.transform_result(gen_table_columns)
|
||||
]:
|
||||
GenUtils.init_column_field(column, table)
|
||||
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column)
|
||||
return True
|
||||
|
||||
# 为每个字段初始化并保存到数据库
|
||||
for column in gen_table_columns:
|
||||
# 将GenTableColumnOutSchema转换为GenTableColumnSchema
|
||||
column_schema = GenTableColumnSchema(
|
||||
table_id=table.table_id,
|
||||
column_name=column.column_name,
|
||||
column_comment=column.column_comment,
|
||||
column_type=column.column_type,
|
||||
is_pk=column.is_pk,
|
||||
is_increment=column.is_increment,
|
||||
is_required=column.is_required,
|
||||
sort=column.sort
|
||||
)
|
||||
# 初始化字段属性
|
||||
GenUtils.init_column_field(column_schema, table)
|
||||
# 保存到数据库
|
||||
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column_schema)
|
||||
return True
|
||||
except Exception as e:
|
||||
raise CustomException(msg=f'导入失败, {str(e)}')
|
||||
|
||||
@@ -128,7 +179,9 @@ class GenTableService:
|
||||
table_names = []
|
||||
for sql_statement in sql_statements:
|
||||
if isinstance(sql_statement, Create):
|
||||
table_names.append(sql_statement.find(Table).name)
|
||||
table = sql_statement.find(Table)
|
||||
if table and table.name:
|
||||
table_names.append(table.name)
|
||||
return table_names
|
||||
|
||||
@classmethod
|
||||
@@ -138,10 +191,19 @@ class GenTableService:
|
||||
gen_table_info = await cls.get_gen_table_by_id_service(auth, table_id)
|
||||
if gen_table_info.id:
|
||||
try:
|
||||
edit_gen_table['options'] = json.dumps(edit_gen_table.get('params'))
|
||||
result = await GenTableCRUD(auth).edit_gen_table(table_id, edit_gen_table)
|
||||
for gen_table_column in data.columns:
|
||||
await GenTableColumnCRUD(auth).update_gen_table_column_crud(table_id, gen_table_column)
|
||||
# 处理params为None的情况
|
||||
params = edit_gen_table.get('params')
|
||||
if params:
|
||||
edit_gen_table['options'] = json.dumps(params)
|
||||
# 将字典转换为GenTableSchema对象
|
||||
gen_table_schema = GenTableSchema(**edit_gen_table)
|
||||
result = await GenTableCRUD(auth).edit_gen_table(table_id, gen_table_schema)
|
||||
# 处理data.columns为None的情况
|
||||
if data.columns:
|
||||
for gen_table_column in data.columns:
|
||||
# 确保column有id字段
|
||||
if hasattr(gen_table_column, 'id') and gen_table_column.id:
|
||||
await GenTableColumnCRUD(auth).update_gen_table_column_crud(gen_table_column.id, gen_table_column)
|
||||
return result.model_dump()
|
||||
except Exception as e:
|
||||
raise CustomException(msg=f'更新失败: {str(e)}')
|
||||
@@ -152,8 +214,10 @@ class GenTableService:
|
||||
async def delete_gen_table_service(cls, auth: AuthSchema, data: GenTableDeleteSchema) -> None:
|
||||
"""删除业务表信息"""
|
||||
try:
|
||||
await GenTableCRUD(auth=auth).delete_gen_table(data)
|
||||
# 先删除相关的字段信息
|
||||
await GenTableColumnCRUD(auth=auth).delete_gen_table_column_by_table_id_dao(data)
|
||||
# 再删除表信息
|
||||
await GenTableCRUD(auth=auth).delete_gen_table(data)
|
||||
except Exception as e:
|
||||
raise CustomException(msg=f'删除失败: {str(e)}')
|
||||
|
||||
@@ -162,7 +226,33 @@ class GenTableService:
|
||||
"""获取需要生成的业务表详细信息"""
|
||||
gen_table = await GenTableCRUD(auth=auth).get_gen_table_by_id(table_id)
|
||||
if gen_table:
|
||||
result = await cls.set_table_from_options(GenTableOutSchema(**CamelCaseUtil.transform_result(gen_table)))
|
||||
# 使用更直接的转换方式
|
||||
result_dict = gen_table.__dict__.copy()
|
||||
result_dict.pop('_sa_instance_state', None)
|
||||
# 确保columns正确加载
|
||||
if hasattr(gen_table, 'columns') and gen_table.columns:
|
||||
columns_list = []
|
||||
for column in gen_table.columns:
|
||||
column_dict = column.__dict__.copy()
|
||||
column_dict.pop('_sa_instance_state', None)
|
||||
# 处理None值,转换为空字符串或适当的默认值
|
||||
for key, value in column_dict.items():
|
||||
if value is None:
|
||||
column_dict[key] = ''
|
||||
columns_list.append(column_dict)
|
||||
result_dict['columns'] = columns_list
|
||||
else:
|
||||
result_dict['columns'] = []
|
||||
# 处理其他None值,特殊处理creator_id和creator字段
|
||||
for key, value in result_dict.items():
|
||||
if value is None:
|
||||
# 对于creator_id和creator字段,保持为None而不是转换为空字符串
|
||||
if key not in ['creator_id', 'creator']:
|
||||
result_dict[key] = ''
|
||||
# 手动创建GenTableOutSchema对象
|
||||
result = GenTableOutSchema(**result_dict)
|
||||
# 设置额外选项
|
||||
result = await cls.set_table_from_options(result)
|
||||
return result
|
||||
else:
|
||||
raise CustomException(msg='业务表不存在')
|
||||
@@ -190,7 +280,10 @@ class GenTableService:
|
||||
await cls.set_pk_column(gen_table)
|
||||
env = Jinja2TemplateInitializerUtil.init_jinja2()
|
||||
context = Jinja2TemplateUtil.prepare_context(gen_table)
|
||||
template_list = Jinja2TemplateUtil.get_template_list(gen_table.tpl_category, gen_table.tpl_web_type)
|
||||
# 处理tpl_category和tpl_web_type为None的情况
|
||||
tpl_category = gen_table.tpl_category or ''
|
||||
tpl_web_type = gen_table.tpl_web_type or ''
|
||||
template_list = Jinja2TemplateUtil.get_template_list(tpl_category, tpl_web_type)
|
||||
preview_code_result = {}
|
||||
for template in template_list:
|
||||
render_content = env.get_template(template).render(**context)
|
||||
@@ -243,12 +336,12 @@ class GenTableService:
|
||||
"""同步数据库"""
|
||||
gen_table = await GenTableCRUD(auth).get_gen_table_by_name(table_name)
|
||||
table = GenTableSchema(**CamelCaseUtil.transform_result(gen_table))
|
||||
table_columns = table.columns
|
||||
# 处理table.columns为None的情况
|
||||
table_columns = table.columns or []
|
||||
table_column_map = {column.column_name: column for column in table_columns}
|
||||
query_db_table_columns = await GenTableColumnCRUD(auth).get_gen_db_table_columns_by_name(table_name)
|
||||
db_table_columns = [
|
||||
GenTableColumnOutSchema(**column) for column in CamelCaseUtil.transform_result(query_db_table_columns)
|
||||
]
|
||||
# 直接使用查询结果,因为get_gen_db_table_columns_by_name已经返回GenTableColumnOutSchema对象列表
|
||||
db_table_columns = query_db_table_columns
|
||||
if not db_table_columns:
|
||||
raise CustomException(msg='同步数据失败,原表结构不存在')
|
||||
db_table_column_names = [column.column_name for column in db_table_columns]
|
||||
@@ -257,25 +350,33 @@ class GenTableService:
|
||||
GenUtils.init_column_field(column, table)
|
||||
if column.column_name in table_column_map:
|
||||
prev_column = table_column_map[column.column_name]
|
||||
column.id = prev_column.id
|
||||
# 处理column.id为None的情况
|
||||
if hasattr(prev_column, 'id') and prev_column.id:
|
||||
column.id = prev_column.id
|
||||
if column.list:
|
||||
column.dict_type = prev_column.dict_type
|
||||
column.query_type = prev_column.query_type
|
||||
if (
|
||||
prev_column.is_required != ''
|
||||
hasattr(prev_column, 'is_required') and prev_column.is_required != ''
|
||||
and not column.pk
|
||||
and (column.insert or column.edit)
|
||||
and (column.usable_column or column.super_column)
|
||||
):
|
||||
column.is_required = prev_column.is_required
|
||||
column.html_type = prev_column.html_type
|
||||
await GenTableColumnCRUD(auth).update_gen_table_column_crud(column.id,column)
|
||||
# 处理column.id为None的情况
|
||||
if hasattr(column, 'id') and column.id:
|
||||
await GenTableColumnCRUD(auth).update_gen_table_column_crud(column.id, column)
|
||||
else:
|
||||
await GenTableColumnCRUD(auth).create_gen_table_column_crud(column)
|
||||
del_columns = [column for column in table_columns if column.column_name not in db_table_column_names]
|
||||
if del_columns:
|
||||
for column in del_columns:
|
||||
await GenTableColumnCRUD(auth).delete_gen_table_column_by_column_id_dao(column.id)
|
||||
# 处理column.id为None的情况
|
||||
if hasattr(column, 'id') and column.id:
|
||||
await GenTableColumnCRUD(auth).delete_gen_table_column_by_column_id_dao(
|
||||
GenTableColumnDeleteSchema(column_ids=[column.id])
|
||||
)
|
||||
except Exception as e:
|
||||
raise e
|
||||
|
||||
@@ -311,7 +412,15 @@ class GenTableService:
|
||||
@classmethod
|
||||
async def set_table_from_options(cls, gen_table: GenTableOutSchema) -> GenTableOutSchema:
|
||||
"""设置代码生成其他选项值"""
|
||||
params_obj = json.loads(gen_table.options) if gen_table.options else None
|
||||
# 处理gen_table.options为None的情况
|
||||
if gen_table.options:
|
||||
try:
|
||||
params_obj = json.loads(gen_table.options)
|
||||
except json.JSONDecodeError:
|
||||
params_obj = {}
|
||||
else:
|
||||
params_obj = {}
|
||||
|
||||
if params_obj:
|
||||
gen_table.tree_code = params_obj.get(GenConstant.TREE_CODE)
|
||||
gen_table.tree_parent_code = params_obj.get(GenConstant.TREE_PARENT_CODE)
|
||||
@@ -329,7 +438,11 @@ class GenTableService:
|
||||
if not edit_gen_table.options:
|
||||
raise CustomException(msg='树表参数不能为空')
|
||||
|
||||
params_obj = json.loads(edit_gen_table.options)
|
||||
# 处理json解析异常
|
||||
try:
|
||||
params_obj = json.loads(edit_gen_table.options)
|
||||
except json.JSONDecodeError:
|
||||
raise CustomException(msg='树表参数格式不正确')
|
||||
|
||||
if GenConstant.TREE_CODE not in params_obj:
|
||||
raise CustomException(msg='树编码字段不能为空')
|
||||
@@ -353,7 +466,16 @@ class GenTableService:
|
||||
:return: 生成代码渲染模板相关信息
|
||||
"""
|
||||
gen_table = await GenTableCRUD(auth=auth).get_gen_table_by_name(table_name)
|
||||
gen_table_schema = GenTableOutSchema(**CamelCaseUtil.transform_result(gen_table))
|
||||
# 检查表是否存在
|
||||
if gen_table is None:
|
||||
raise CustomException(msg=f"业务表 {table_name} 不存在")
|
||||
|
||||
# 确保CamelCaseUtil.transform_result返回的是字典
|
||||
transformed_result = CamelCaseUtil.transform_result(gen_table)
|
||||
if transformed_result is None:
|
||||
raise CustomException(msg=f"业务表 {table_name} 数据转换失败")
|
||||
|
||||
gen_table_schema = GenTableOutSchema(**transformed_result)
|
||||
await cls.set_sub_table(auth, gen_table_schema)
|
||||
await cls.set_pk_column(gen_table_schema)
|
||||
context = Jinja2TemplateUtil.prepare_context(gen_table_schema)
|
||||
@@ -361,7 +483,12 @@ class GenTableService:
|
||||
gen_table_schema.tpl_category or "",
|
||||
gen_table_schema.tpl_web_type or ""
|
||||
)
|
||||
output_files = [Jinja2TemplateUtil.get_file_name([template], gen_table_schema)[0] for template in template_list]
|
||||
# 修复:确保get_file_name返回的文件名不为空
|
||||
output_files = []
|
||||
for template in template_list:
|
||||
file_name = Jinja2TemplateUtil.get_file_name([template], gen_table_schema)
|
||||
if file_name: # 只有当文件名不为空时才添加到列表中
|
||||
output_files.append(file_name)
|
||||
|
||||
return [template_list, output_files, context, gen_table_schema]
|
||||
|
||||
@@ -371,11 +498,13 @@ class GenTableService:
|
||||
"""根据GenTableModel对象和模板名称生成路径"""
|
||||
try:
|
||||
gen_path = gen_table.gen_path or ""
|
||||
file_name = Jinja2TemplateUtil.get_file_name([template], gen_table)
|
||||
# 修复:检查文件名是否为空
|
||||
if not file_name:
|
||||
return None
|
||||
if gen_path == '/':
|
||||
file_name = Jinja2TemplateUtil.get_file_name([template], gen_table)[0]
|
||||
return os.path.join(os.getcwd(), GEN_PATH, file_name)
|
||||
else:
|
||||
file_name = Jinja2TemplateUtil.get_file_name([template], gen_table)[0]
|
||||
return os.path.join(gen_path, file_name)
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user