diff --git a/backend/plugin/code_generator/README.md b/backend/plugin/code_generator/README.md index d7c82353..70a9649d 100644 --- a/backend/plugin/code_generator/README.md +++ b/backend/plugin/code_generator/README.md @@ -12,7 +12,7 @@ 包含代码生成的相关配置,详情查看:`generator/model/gen_business.py` -### 2. 代码生成模型 +### 2. 代码生成模型列 包含代码生成所需要的模型列信息,就像正常定义模型列一样,目前支持的功能有限 diff --git a/backend/plugin/code_generator/api/router.py b/backend/plugin/code_generator/api/router.py index bd601e28..b0ba842f 100644 --- a/backend/plugin/code_generator/api/router.py +++ b/backend/plugin/code_generator/api/router.py @@ -5,10 +5,10 @@ from backend.core.conf import settings from backend.plugin.code_generator.api.v1.business import router as business_router from backend.plugin.code_generator.api.v1.code import router as gen_router -from backend.plugin.code_generator.api.v1.column import router as model_router +from backend.plugin.code_generator.api.v1.column import router as column_router v1 = APIRouter(prefix=f'{settings.FASTAPI_API_V1_PATH}/generates', tags=['代码生成']) v1.include_router(business_router, prefix='/businesses') -v1.include_router(model_router, prefix='/models') +v1.include_router(column_router, prefix='/columns') v1.include_router(gen_router, prefix='/codes') diff --git a/backend/plugin/code_generator/api/v1/business.py b/backend/plugin/code_generator/api/v1/business.py index 842b3b8b..a77e7924 100644 --- a/backend/plugin/code_generator/api/v1/business.py +++ b/backend/plugin/code_generator/api/v1/business.py @@ -15,13 +15,19 @@ GetGenBusinessDetail, UpdateGenBusinessParam, ) -from backend.plugin.code_generator.schema.column import GetGenModelDetail +from backend.plugin.code_generator.schema.column import GetGenColumnDetail from backend.plugin.code_generator.service.business_service import gen_business_service -from backend.plugin.code_generator.service.column_service import gen_model_service +from backend.plugin.code_generator.service.column_service import gen_column_service router = APIRouter() +@router.get('/all', summary='获取所有代码生成业务', dependencies=[DependsJwtAuth]) +async def get_all_businesses() -> ResponseSchemaModel[list[GetGenBusinessDetail]]: + data = await gen_business_service.get_all() + return response_base.success(data=data) + + @router.get('/{pk}', summary='获取代码生成业务详情', dependencies=[DependsJwtAuth]) async def get_business( pk: Annotated[int, Path(description='业务 ID')], @@ -47,11 +53,11 @@ async def get_businesses_paged( return response_base.success(data=page_data) -@router.get('/{pk}/models', summary='获取代码生成业务所有模型', dependencies=[DependsJwtAuth]) -async def get_business_all_models( +@router.get('/{pk}/columns', summary='获取代码生成业务所有模型列', dependencies=[DependsJwtAuth]) +async def get_business_all_columns( pk: Annotated[int, Path(description='业务 ID')], -) -> ResponseSchemaModel[list[GetGenModelDetail]]: - data = await gen_model_service.get_models(business_id=pk) +) -> ResponseSchemaModel[list[GetGenColumnDetail]]: + data = await gen_column_service.get_columns(business_id=pk) return response_base.success(data=data) diff --git a/backend/plugin/code_generator/api/v1/code.py b/backend/plugin/code_generator/api/v1/code.py index b4d8713d..69c8e026 100644 --- a/backend/plugin/code_generator/api/v1/code.py +++ b/backend/plugin/code_generator/api/v1/code.py @@ -19,7 +19,7 @@ @router.get('/tables', summary='获取数据库表') async def get_all_tables( table_schema: Annotated[str, Query(description='数据库名')] = 'fba', -) -> ResponseSchemaModel[list[str]]: +) -> ResponseSchemaModel[list[dict[str, str]]]: data = await gen_service.get_tables(table_schema=table_schema) return response_base.success(data=data) diff --git a/backend/plugin/code_generator/api/v1/column.py b/backend/plugin/code_generator/api/v1/column.py index 1e5b9696..6a252649 100644 --- a/backend/plugin/code_generator/api/v1/column.py +++ b/backend/plugin/code_generator/api/v1/column.py @@ -8,47 +8,47 @@ from backend.common.security.jwt import DependsJwtAuth from backend.common.security.permission import RequestPermission from backend.common.security.rbac import DependsRBAC -from backend.plugin.code_generator.schema.column import CreateGenModelParam, GetGenModelDetail, UpdateGenModelParam -from backend.plugin.code_generator.service.column_service import gen_model_service +from backend.plugin.code_generator.schema.column import CreateGenColumnParam, GetGenColumnDetail, UpdateGenColumnParam +from backend.plugin.code_generator.service.column_service import gen_column_service router = APIRouter() @router.get('/types', summary='获取代码生成模型列类型', dependencies=[DependsJwtAuth]) -async def get_model_types() -> ResponseSchemaModel[list[str]]: - model_types = await gen_model_service.get_types() - return response_base.success(data=model_types) +async def get_column_types() -> ResponseSchemaModel[list[str]]: + column_types = await gen_column_service.get_types() + return response_base.success(data=column_types) -@router.get('/{pk}', summary='获取代码生成模型详情', dependencies=[DependsJwtAuth]) -async def get_model(pk: Annotated[int, Path(description='模型 ID')]) -> ResponseSchemaModel[GetGenModelDetail]: - data = await gen_model_service.get(pk=pk) +@router.get('/{pk}', summary='获取代码生成模型列详情', dependencies=[DependsJwtAuth]) +async def get_column(pk: Annotated[int, Path(description='模型列 ID')]) -> ResponseSchemaModel[GetGenColumnDetail]: + data = await gen_column_service.get(pk=pk) return response_base.success(data=data) @router.post( '', - summary='创建代码生成模型', + summary='创建代码生成模型列', dependencies=[ - Depends(RequestPermission('codegen:model:add')), + Depends(RequestPermission('codegen:column:add')), DependsRBAC, ], ) -async def create_model(obj: CreateGenModelParam) -> ResponseModel: - await gen_model_service.create(obj=obj) +async def create_column(obj: CreateGenColumnParam) -> ResponseModel: + await gen_column_service.create(obj=obj) return response_base.success() @router.put( '/{pk}', - summary='更新代码生成模型', + summary='更新代码生成模型列', dependencies=[ - Depends(RequestPermission('codegen:model:edit')), + Depends(RequestPermission('codegen:column:edit')), DependsRBAC, ], ) -async def update_model(pk: Annotated[int, Path(description='模型 ID')], obj: UpdateGenModelParam) -> ResponseModel: - count = await gen_model_service.update(pk=pk, obj=obj) +async def update_column(pk: Annotated[int, Path(description='模型列 ID')], obj: UpdateGenColumnParam) -> ResponseModel: + count = await gen_column_service.update(pk=pk, obj=obj) if count > 0: return response_base.success() return response_base.fail() @@ -56,14 +56,14 @@ async def update_model(pk: Annotated[int, Path(description='模型 ID')], obj: U @router.delete( '/{pk}', - summary='删除代码生成模型', + summary='删除代码生成模型列', dependencies=[ - Depends(RequestPermission('codegen:model:del')), + Depends(RequestPermission('codegen:column:del')), DependsRBAC, ], ) -async def delete_model(pk: Annotated[int, Path(description='模型 ID')]) -> ResponseModel: - count = await gen_model_service.delete(pk=pk) +async def delete_column(pk: Annotated[int, Path(description='模型列 ID')]) -> ResponseModel: + count = await gen_column_service.delete(pk=pk) if count > 0: return response_base.success() return response_base.fail() diff --git a/backend/plugin/code_generator/crud/crud_business.py b/backend/plugin/code_generator/crud/crud_business.py index 00dbcb89..5f2d4d71 100644 --- a/backend/plugin/code_generator/crud/crud_business.py +++ b/backend/plugin/code_generator/crud/crud_business.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from typing import Sequence from sqlalchemy import Select from sqlalchemy.ext.asyncio import AsyncSession @@ -32,6 +33,15 @@ async def get_by_name(self, db: AsyncSession, name: str) -> GenBusiness | None: """ return await self.select_model_by_column(db, table_name=name) + async def get_all(self, db: AsyncSession) -> Sequence[GenBusiness]: + """ + 获取所有代码生成业务 + + :param db: 数据库会话 + :return: + """ + return await self.select_models(db) + async def get_list(self, table_name: str | None) -> Select: """ 获取所有代码生成业务 @@ -44,7 +54,7 @@ async def get_list(self, table_name: str | None) -> Select: if table_name is not None: filters['table_name__like'] = f'%{table_name}%' - return await self.select_order('id', 'desc', **filters) + return await self.select_order('id', 'desc', load_strategies={'gen_column': 'noload'}, **filters) async def create(self, db: AsyncSession, obj: CreateGenBusinessParam) -> None: """ diff --git a/backend/plugin/code_generator/crud/crud_code.py b/backend/plugin/code_generator/crud/crud_code.py index d95efc8a..a756cfc9 100644 --- a/backend/plugin/code_generator/crud/crud_code.py +++ b/backend/plugin/code_generator/crud/crud_code.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from typing import Sequence -from sqlalchemy import Row, text +from sqlalchemy import Row, RowMapping, text from sqlalchemy.ext.asyncio import AsyncSession from backend.core.conf import settings @@ -12,7 +12,7 @@ class CRUDGen: """代码生成 CRUD 类""" @staticmethod - async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[str]: + async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[RowMapping]: """ 获取所有表名 @@ -22,20 +22,23 @@ async def get_all_tables(db: AsyncSession, table_schema: str) -> Sequence[str]: """ if settings.DATABASE_TYPE == 'mysql': sql = """ - SELECT table_name AS table_name FROM information_schema.tables - WHERE table_name NOT LIKE 'sys_gen_%' + SELECT table_name AS table_name, table_comment AS table_comment + FROM information_schema.tables + WHERE table_name NOT LIKE 'sys_gen_%' AND table_schema = :table_schema; """ else: sql = """ - SELECT table_name AS table_name FROM information_schema.tables - WHERE table_name NOT LIKE 'sys_gen_%' - AND table_catalog = :table_schema - AND table_schema = 'public'; -- schema 通常是 'public' + SELECT c.relname AS table_name, obj_description(c.oid) AS table_comment + FROM pg_class c + LEFT JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'r' + AND n.nspname = 'public' -- schema 通常是 'public' + AND c.relname NOT LIKE 'sys_gen_%'; """ stmt = text(sql).bindparams(table_schema=table_schema) result = await db.execute(stmt) - return result.scalars().all() + return result.mappings().all() @staticmethod async def get_table(db: AsyncSession, table_name: str) -> Row[tuple]: @@ -48,18 +51,19 @@ async def get_table(db: AsyncSession, table_name: str) -> Row[tuple]: """ if settings.DATABASE_TYPE == 'mysql': sql = """ - SELECT table_name AS table_name, table_comment AS table_comment FROM information_schema.tables + SELECT table_name AS table_name, table_comment AS table_comment + FROM information_schema.tables WHERE table_name NOT LIKE 'sys_gen_%' AND table_name = :table_name; """ else: sql = """ - SELECT t.tablename AS table_name, - pg_catalog.obj_description(t.tablename::regclass, 'pg_class') AS table_comment - FROM pg_tables t - WHERE t.tablename NOT LIKE 'sys_gen_%' - AND t.tablename = :table_name - AND t.schemaname = 'public'; -- schema 通常是 'public' + SELECT c.relname AS table_name, obj_description(c.oid) AS table_comment + FROM pg_class c + LEFT JOIN pg_namespace n ON n.oid = c.relnamespace + WHERE c.relkind = 'r' + AND n.nspname = 'public' -- schema 通常是 'public' + AND c.relname NOT LIKE 'sys_gen_%'; """ stmt = text(sql).bindparams(table_name=table_name) result = await db.execute(stmt) diff --git a/backend/plugin/code_generator/crud/crud_column.py b/backend/plugin/code_generator/crud/crud_column.py index 9c498d9b..57d4e688 100644 --- a/backend/plugin/code_generator/crud/crud_column.py +++ b/backend/plugin/code_generator/crud/crud_column.py @@ -6,11 +6,11 @@ from sqlalchemy_crud_plus import CRUDPlus from backend.plugin.code_generator.model import GenColumn -from backend.plugin.code_generator.schema.column import CreateGenModelParam, UpdateGenModelParam +from backend.plugin.code_generator.schema.column import CreateGenColumnParam, UpdateGenColumnParam -class CRUDGenModel(CRUDPlus[GenColumn]): - """代码生成模型 CRUD 类""" +class CRUDGenColumn(CRUDPlus[GenColumn]): + """代码生成模型列 CRUD 类""" async def get(self, db: AsyncSession, pk: int) -> GenColumn | None: """ @@ -32,24 +32,24 @@ async def get_all_by_business(self, db: AsyncSession, business_id: int) -> Seque """ return await self.select_models_order(db, sort_columns='sort', gen_business_id=business_id) - async def create(self, db: AsyncSession, obj: CreateGenModelParam, pd_type: str | None) -> None: + async def create(self, db: AsyncSession, obj: CreateGenColumnParam, pd_type: str | None) -> None: """ - 创建代码生成模型 + 创建代码生成模型列 :param db: 数据库会话 - :param obj: 创建代码生成模型参数 + :param obj: 创建代码生成模型列参数 :param pd_type: Pydantic 类型 :return: """ await self.create_model(db, obj, pd_type=pd_type) - async def update(self, db: AsyncSession, pk: int, obj: UpdateGenModelParam, pd_type: str | None) -> int: + async def update(self, db: AsyncSession, pk: int, obj: UpdateGenColumnParam, pd_type: str | None) -> int: """ - 更新代码生成模型 + 更新代码生成模型列 :param db: 数据库会话 - :param pk: 代码生成模型 ID - :param obj: 更新代码生成模型参数 + :param pk: 代码生成模型列 ID + :param obj: 更新代码生成模型列参数 :param pd_type: Pydantic 类型 :return: """ @@ -57,13 +57,13 @@ async def update(self, db: AsyncSession, pk: int, obj: UpdateGenModelParam, pd_t async def delete(self, db: AsyncSession, pk: int) -> int: """ - 删除代码生成模型 + 删除代码生成模型列 :param db: 数据库会话 - :param pk: 代码生成模型 ID + :param pk: 代码生成模型列 ID :return: """ return await self.delete_model(db, pk) -gen_model_dao: CRUDGenModel = CRUDGenModel(GenColumn) +gen_column_dao: CRUDGenColumn = CRUDGenColumn(GenColumn) diff --git a/backend/plugin/code_generator/enums.py b/backend/plugin/code_generator/enums.py index 65c18b15..ac207f5f 100644 --- a/backend/plugin/code_generator/enums.py +++ b/backend/plugin/code_generator/enums.py @@ -3,7 +3,7 @@ from backend.common.enums import StrEnum -class GenModelMySQLColumnType(StrEnum): +class GenMySQLColumnType(StrEnum): """代码生成模型列类型(MySQL)""" # Python 类型映射 @@ -68,7 +68,7 @@ class GenModelMySQLColumnType(StrEnum): YEAR = 'int' -class GenModelPostgreSQLColumnType(StrEnum): +class GenPostgreSQLColumnType(StrEnum): """代码生成模型列类型(PostgreSQL)""" # Python 类型映射 diff --git a/backend/plugin/code_generator/model/business.py b/backend/plugin/code_generator/model/business.py index c963f17b..561aedad 100644 --- a/backend/plugin/code_generator/model/business.py +++ b/backend/plugin/code_generator/model/business.py @@ -33,5 +33,5 @@ class GenBusiness(Base): remark: Mapped[str | None] = mapped_column( LONGTEXT().with_variant(TEXT, 'postgresql'), default=None, comment='备注' ) - # 代码生成业务模型一对多 + # 代码生成业务模型列一对多 gen_column: Mapped[list['GenColumn']] = relationship(init=False, back_populates='gen_business') diff --git a/backend/plugin/code_generator/model/column.py b/backend/plugin/code_generator/model/column.py index 1357aa0f..818eb875 100644 --- a/backend/plugin/code_generator/model/column.py +++ b/backend/plugin/code_generator/model/column.py @@ -31,7 +31,7 @@ class GenColumn(DataClassBase): is_pk: Mapped[bool] = mapped_column(default=False, comment='是否主键') is_nullable: Mapped[bool] = mapped_column(default=False, comment='是否可为空') - # 代码生成业务模型一对多 + # 代码生成业务模型列一对多 gen_business_id: Mapped[int] = mapped_column( BigInteger, ForeignKey('gen_business.id', ondelete='CASCADE'), default=0, comment='代码生成业务ID' ) diff --git a/backend/plugin/code_generator/plugin.toml b/backend/plugin/code_generator/plugin.toml index a3e588d5..4004a2b3 100644 --- a/backend/plugin/code_generator/plugin.toml +++ b/backend/plugin/code_generator/plugin.toml @@ -1,6 +1,6 @@ [plugin] summary = '代码生成' -version = '0.0.2' +version = '0.0.3' description = '生成通用业务代码' author = 'wu-clan' diff --git a/backend/plugin/code_generator/schema/business.py b/backend/plugin/code_generator/schema/business.py index 56367d3d..18deaf50 100644 --- a/backend/plugin/code_generator/schema/business.py +++ b/backend/plugin/code_generator/schema/business.py @@ -14,12 +14,12 @@ class GenBusinessSchemaBase(SchemaBase): table_name: str = Field(description='表名称(英文)') doc_comment: str = Field(description='文档注释(用于函数/参数文档)') table_comment: str | None = Field(None, description='表描述') - class_name: str | None = Field(None, description='基础类名 (默认为英文表名称)') - schema_name: str | None = Field(None, description='Schema 名称 (默认为英文表名称)') - filename: str | None = Field(None, description='基础文件名(默认为英文表名称)') + class_name: str | None = Field(None, description='用于 python 代码基础类名') + schema_name: str | None = Field(None, description='用于 python Schema 代码基础类名') + filename: str | None = Field(None, description='用于 python 代码基础文件名') default_datetime_column: bool = Field(True, description='是否存在默认时间列') api_version: str = Field('v1', description='代码生成 api 版本') - gen_path: str | None = Field(None, description='代码生成路径(默认为 app 根路径)') + gen_path: str | None = Field(None, description='代码生成路径') remark: str | None = Field(None, description='备注') diff --git a/backend/plugin/code_generator/schema/column.py b/backend/plugin/code_generator/schema/column.py index a3fccce4..69fa185a 100644 --- a/backend/plugin/code_generator/schema/column.py +++ b/backend/plugin/code_generator/schema/column.py @@ -6,7 +6,7 @@ from backend.plugin.code_generator.utils.type_conversion import sql_type_to_sqlalchemy -class GenModelSchemaBase(SchemaBase): +class GenColumnSchemaBase(SchemaBase): """代码生成模型基础模型""" name: str = Field(description='列名称') @@ -26,16 +26,16 @@ def type_update(cls, v: str) -> str: return sql_type_to_sqlalchemy(v) -class CreateGenModelParam(GenModelSchemaBase): - """创建代码生成模型参数""" +class CreateGenColumnParam(GenColumnSchemaBase): + """创建代码生成模型列参数""" -class UpdateGenModelParam(GenModelSchemaBase): - """更新代码生成模型参数""" +class UpdateGenColumnParam(GenColumnSchemaBase): + """更新代码生成模型列参数""" -class GetGenModelDetail(GenModelSchemaBase): - """获取代码生成模型详情""" +class GetGenColumnDetail(GenColumnSchemaBase): + """获取代码生成模型列详情""" model_config = ConfigDict(from_attributes=True) diff --git a/backend/plugin/code_generator/service/business_service.py b/backend/plugin/code_generator/service/business_service.py index eec2721d..7c829615 100644 --- a/backend/plugin/code_generator/service/business_service.py +++ b/backend/plugin/code_generator/service/business_service.py @@ -1,5 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- +from typing import Sequence from sqlalchemy import Select @@ -27,6 +28,12 @@ async def get(*, pk: int) -> GenBusiness: raise errors.NotFoundError(msg='代码生成业务不存在') return business + @staticmethod + async def get_all() -> Sequence[GenBusiness]: + """获取所有业务""" + async with async_db_session() as db: + return await gen_business_dao.get_all(db) + @staticmethod async def get_select(*, table_name: str) -> Select: """ diff --git a/backend/plugin/code_generator/service/code_service.py b/backend/plugin/code_generator/service/code_service.py index 4720b90f..f93fe053 100644 --- a/backend/plugin/code_generator/service/code_service.py +++ b/backend/plugin/code_generator/service/code_service.py @@ -10,18 +10,19 @@ import aiofiles from pydantic.alias_generators import to_pascal +from sqlalchemy import RowMapping from backend.common.exception import errors from backend.core.path_conf import BASE_PATH from backend.database.db import async_db_session from backend.plugin.code_generator.crud.crud_business import gen_business_dao from backend.plugin.code_generator.crud.crud_code import gen_dao -from backend.plugin.code_generator.crud.crud_column import gen_model_dao +from backend.plugin.code_generator.crud.crud_column import gen_column_dao from backend.plugin.code_generator.model import GenBusiness from backend.plugin.code_generator.schema.business import CreateGenBusinessParam from backend.plugin.code_generator.schema.code import ImportParam -from backend.plugin.code_generator.schema.column import CreateGenModelParam -from backend.plugin.code_generator.service.column_service import gen_model_service +from backend.plugin.code_generator.schema.column import CreateGenColumnParam +from backend.plugin.code_generator.service.column_service import gen_column_service from backend.plugin.code_generator.utils.code_template import gen_template from backend.plugin.code_generator.utils.type_conversion import sql_type_to_pydantic @@ -30,7 +31,7 @@ class GenService: """代码生成服务类""" @staticmethod - async def get_tables(*, table_schema: str) -> Sequence[str]: + async def get_tables(*, table_schema: str) -> Sequence[RowMapping]: """ 获取指定 schema 下的所有表名 @@ -43,7 +44,7 @@ async def get_tables(*, table_schema: str) -> Sequence[str]: @staticmethod async def import_business_and_model(*, obj: ImportParam) -> None: """ - 导入业务和模型数据 + 导入业务和模型列数据 :param obj: 导入参数对象 :return: @@ -64,8 +65,8 @@ async def import_business_and_model(*, obj: ImportParam) -> None: table_name=table_name, doc_comment=table_info[1] or table_name.split('_')[-1], table_comment=table_info[1], - class_name=table_name, - schema_name=table_name, + class_name=to_pascal(table_name), + schema_name=to_pascal(table_name), filename=table_name, ).model_dump() ) @@ -76,9 +77,9 @@ async def import_business_and_model(*, obj: ImportParam) -> None: for column in column_info: column_type = column[-1].split('(')[0].upper() pd_type = sql_type_to_pydantic(column_type) - await gen_model_dao.create( + await gen_column_dao.create( db, - CreateGenModelParam( + CreateGenColumnParam( name=column[0], comment=column[-2], type=column_type, @@ -99,7 +100,7 @@ async def render_tpl_code(*, business: GenBusiness) -> dict[str, str]: :param business: 业务对象 :return: """ - gen_models = await gen_model_service.get_models(business_id=business.id) + gen_models = await gen_column_service.get_columns(business_id=business.id) if not gen_models: raise errors.NotFoundError(msg='代码生成模型表为空') @@ -126,7 +127,20 @@ async def preview(self, *, pk: int) -> dict[str, bytes]: codes = {} for tpl, code in tpl_code_map.items(): if tpl.startswith('python'): - codes[tpl.replace('.jinja', '.py').split('/')[-1]] = code.encode('utf-8') + rootpath = f'fastapi_best_architecture/backend/app/{business.app_name}' + template_name = tpl.split('/')[-1] + match template_name: + case 'api.jinja': + filepath = f'{rootpath}/api/{business.api_version}/{business.app_name}.py' + case 'crud.jinja': + filepath = f'{rootpath}/crud/crud_{business.app_name}.py' + case 'model.jinja': + filepath = f'{rootpath}/model/{business.app_name}.py' + case 'schema.jinja': + filepath = f'{rootpath}/schema/{business.app_name}.py' + case 'service.jinja': + filepath = f'{rootpath}/service/{business.app_name}_service.py' + codes[filepath] = code.encode('utf-8') return codes diff --git a/backend/plugin/code_generator/service/column_service.py b/backend/plugin/code_generator/service/column_service.py index 7879b71b..ef501c55 100644 --- a/backend/plugin/code_generator/service/column_service.py +++ b/backend/plugin/code_generator/service/column_service.py @@ -4,93 +4,93 @@ from backend.common.exception import errors from backend.database.db import async_db_session -from backend.plugin.code_generator.crud.crud_column import gen_model_dao -from backend.plugin.code_generator.enums import GenModelMySQLColumnType +from backend.plugin.code_generator.crud.crud_column import gen_column_dao +from backend.plugin.code_generator.enums import GenMySQLColumnType from backend.plugin.code_generator.model import GenColumn -from backend.plugin.code_generator.schema.column import CreateGenModelParam, UpdateGenModelParam +from backend.plugin.code_generator.schema.column import CreateGenColumnParam, UpdateGenColumnParam from backend.plugin.code_generator.utils.type_conversion import sql_type_to_pydantic -class GenModelService: - """代码生成模型服务类""" +class GenColumnService: + """代码生成模型列服务类""" @staticmethod async def get(*, pk: int) -> GenColumn: """ - 获取指定 ID 的模型 + 获取指定 ID 的模型列 - :param pk: 模型 ID + :param pk: 模型列 ID :return: """ async with async_db_session() as db: - model = await gen_model_dao.get(db, pk) - if not model: - raise errors.NotFoundError(msg='代码生成模型不存在') - return model + column = await gen_column_dao.get(db, pk) + if not column: + raise errors.NotFoundError(msg='代码生成模型列不存在') + return column @staticmethod async def get_types() -> list[str]: """获取所有 MySQL 列类型""" - types = GenModelMySQLColumnType.get_member_keys() + types = GenMySQLColumnType.get_member_keys() types.sort() return types @staticmethod - async def get_models(*, business_id: int) -> Sequence[GenColumn]: + async def get_columns(*, business_id: int) -> Sequence[GenColumn]: """ - 获取指定业务的所有模型 + 获取指定业务的所有模型列 :param business_id: 业务 ID :return: """ async with async_db_session() as db: - return await gen_model_dao.get_all_by_business(db, business_id) + return await gen_column_dao.get_all_by_business(db, business_id) @staticmethod - async def create(*, obj: CreateGenModelParam) -> None: + async def create(*, obj: CreateGenColumnParam) -> None: """ - 创建模型 + 创建模型列 - :param obj: 创建模型参数 + :param obj: 创建模型列参数 :return: """ async with async_db_session.begin() as db: - gen_models = await gen_model_dao.get_all_by_business(db, obj.gen_business_id) - if obj.name in [gen_model.name for gen_model in gen_models]: - raise errors.ForbiddenError(msg='禁止添加相同列到同一模型表') + gen_columns = await gen_column_dao.get_all_by_business(db, obj.gen_business_id) + if obj.name in [gen_column.name for gen_column in gen_columns]: + raise errors.ForbiddenError(msg='模型列已存在') pd_type = sql_type_to_pydantic(obj.type) - await gen_model_dao.create(db, obj, pd_type=pd_type) + await gen_column_dao.create(db, obj, pd_type=pd_type) @staticmethod - async def update(*, pk: int, obj: UpdateGenModelParam) -> int: + async def update(*, pk: int, obj: UpdateGenColumnParam) -> int: """ - 更新模型 + 更新模型列 - :param pk: 模型 ID - :param obj: 更新模型参数 + :param pk: 模型列 ID + :param obj: 更新模型列参数 :return: """ async with async_db_session.begin() as db: - model = await gen_model_dao.get(db, pk) - if obj.name != model.name: - gen_models = await gen_model_dao.get_all_by_business(db, obj.gen_business_id) - if obj.name in [gen_model.name for gen_model in gen_models]: + column = await gen_column_dao.get(db, pk) + if obj.name != column.name: + gen_columns = await gen_column_dao.get_all_by_business(db, obj.gen_business_id) + if obj.name in [gen_column.name for gen_column in gen_columns]: raise errors.ConflictError(msg='模型列名已存在') pd_type = sql_type_to_pydantic(obj.type) - return await gen_model_dao.update(db, pk, obj, pd_type=pd_type) + return await gen_column_dao.update(db, pk, obj, pd_type=pd_type) @staticmethod async def delete(*, pk: int) -> int: """ - 删除模型 + 删除模型列 - :param pk: 模型 ID + :param pk: 模型列 ID :return: """ async with async_db_session.begin() as db: - return await gen_model_dao.delete(db, pk) + return await gen_column_dao.delete(db, pk) -gen_model_service: GenModelService = GenModelService() +gen_column_service: GenColumnService = GenColumnService() diff --git a/backend/plugin/code_generator/templates/python/crud.jinja b/backend/plugin/code_generator/templates/python/crud.jinja index 2d30bdd8..4f9b33b9 100644 --- a/backend/plugin/code_generator/templates/python/crud.jinja +++ b/backend/plugin/code_generator/templates/python/crud.jinja @@ -23,7 +23,7 @@ class CRUD{{ class_name }}(CRUDPlus[{{ schema_name }}]): async def get_list(self) -> Select: """获取{{ doc_comment }}列表""" - return await self.select_order('created_time', 'desc') + return await self.select_order('id', 'desc') async def get_all(self, db: AsyncSession) -> Sequence[{{ class_name }}]: """ diff --git a/backend/plugin/code_generator/utils/type_conversion.py b/backend/plugin/code_generator/utils/type_conversion.py index 9520f2a7..64c134ae 100644 --- a/backend/plugin/code_generator/utils/type_conversion.py +++ b/backend/plugin/code_generator/utils/type_conversion.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- from backend.core.conf import settings -from backend.plugin.code_generator.enums import GenModelMySQLColumnType, GenModelPostgreSQLColumnType +from backend.plugin.code_generator.enums import GenMySQLColumnType, GenPostgreSQLColumnType def sql_type_to_sqlalchemy(typing: str) -> str: @@ -12,10 +12,10 @@ def sql_type_to_sqlalchemy(typing: str) -> str: :return: """ if settings.DATABASE_TYPE == 'mysql': - if typing in GenModelMySQLColumnType.get_member_keys(): + if typing in GenMySQLColumnType.get_member_keys(): return typing else: - if typing in GenModelPostgreSQLColumnType.get_member_keys(): + if typing in GenPostgreSQLColumnType.get_member_keys(): return typing return 'String' @@ -29,9 +29,9 @@ def sql_type_to_pydantic(typing: str) -> str: """ try: if settings.DATABASE_TYPE == 'mysql': - return GenModelMySQLColumnType[typing].value + return GenMySQLColumnType[typing].value if typing == 'CHARACTER VARYING': # postgresql 中 DDL VARCHAR 的别名 return 'str' - return GenModelPostgreSQLColumnType[typing].value + return GenPostgreSQLColumnType[typing].value except KeyError: return 'str'