diff --git a/app/__init__.py b/app/__init__.py index 5b1bbfc..50a398f 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -1,11 +1,13 @@ +from contextlib import asynccontextmanager + from fastapi import FastAPI +from tortoise import Tortoise from app.core.exceptions import SettingNotFound from app.core.init_app import ( init_menus, init_superuser, make_middlewares, - register_db, register_exceptions, register_routers, ) @@ -16,6 +18,16 @@ except ImportError: raise SettingNotFound("Can not import settings") +@asynccontextmanager +async def lifespan(app: FastAPI): + await Tortoise.init(config=settings.TORTOISE_ORM) + await Tortoise.generate_schemas() + await init_superuser() + await init_menus() + yield + await Tortoise.close_connections() + + def create_app() -> FastAPI: app = FastAPI( title=settings.APP_TITLE, @@ -23,17 +35,11 @@ def create_app() -> FastAPI: version=settings.VERSION, openapi_url="/openapi.json", middleware=make_middlewares(), + lifespan=lifespan, ) - register_db(app) register_exceptions(app) register_routers(app, prefix="/api") return app app = create_app() - - -@app.on_event("startup") -async def startup_event(): - await init_superuser() - await init_menus() diff --git a/app/api/v1/__init__.py b/app/api/v1/__init__.py index 4f787b1..76a14be 100644 --- a/app/api/v1/__init__.py +++ b/app/api/v1/__init__.py @@ -4,10 +4,10 @@ from app.core.dependency import DependPermisson from .apis import apis_router from .base import base_router +from .depts import depts_router from .menus import menus_router from .roles import roles_router from .users import users_router -from .depts import depts_router v1_router = APIRouter() diff --git a/app/api/v1/apis/apis.py b/app/api/v1/apis/apis.py index 8d5e97b..7aef2d7 100644 --- a/app/api/v1/apis/apis.py +++ b/app/api/v1/apis/apis.py @@ -10,6 +10,7 @@ from app.schemas.apis import * router = APIRouter() + @router.get("/list", summary="查看API列表") async def list_api( page: int = Query(1, description="页码"), diff --git a/app/api/v1/depts/depts.py b/app/api/v1/depts/depts.py index 6a0ce7d..a22ef0a 100644 --- a/app/api/v1/depts/depts.py +++ b/app/api/v1/depts/depts.py @@ -1,8 +1,7 @@ from fastapi import APIRouter, Query from app.controllers.dept import dept_controller -from app.log import logger -from app.schemas import Success, SuccessExtra +from app.schemas import Success from app.schemas.depts import * router = APIRouter() @@ -46,4 +45,4 @@ async def delete_dept( dept_id: int = Query(..., description="部门ID"), ): await dept_controller.delete_dept(dept_id=dept_id) - return Success(msg="Deleted Success") \ No newline at end of file + return Success(msg="Deleted Success") diff --git a/app/api/v1/users/users.py b/app/api/v1/users/users.py index 9d4cbc1..a11cd4e 100644 --- a/app/api/v1/users/users.py +++ b/app/api/v1/users/users.py @@ -4,10 +4,10 @@ from fastapi import APIRouter, Query from fastapi.exceptions import HTTPException from tortoise.expressions import Q +from app.controllers.dept import dept_controller from app.controllers.user import UserController from app.schemas.base import Success, SuccessExtra from app.schemas.users import * -from app.controllers.dept import dept_controller logger = logging.getLogger(__name__) @@ -20,7 +20,7 @@ async def list_user( page_size: int = Query(10, description="每页数量"), username: str = Query("", description="用户名称,用于搜索"), email: str = Query("", description="邮箱地址"), - dept_id: int = Query(None, description="部门ID") + dept_id: int = Query(None, description="部门ID"), ): user_controller = UserController() q = Q() diff --git a/app/controllers/dept.py b/app/controllers/dept.py index 608c866..0dbb5fa 100644 --- a/app/controllers/dept.py +++ b/app/controllers/dept.py @@ -1,8 +1,9 @@ +from tortoise.expressions import Q +from tortoise.transactions import atomic + from app.core.crud import CRUDBase from app.models.admin import Dept, DeptClosure from app.schemas.depts import DeptCreate, DeptUpdate -from tortoise.transactions import atomic -from tortoise.expressions import Q class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): @@ -15,19 +16,21 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): q &= Q(is_deleted=False) if name: q &= Q(name__contains=name) - all_depts = await self.model.filter(q).order_by('order') + all_depts = await self.model.filter(q).order_by("order") + # 辅助函数,用于递归构建部门树 def build_tree(parent_id): return [ { - 'id': dept.id, - 'name': dept.name, - 'desc': dept.desc, - 'order': dept.order, - 'parent_id': dept.parent_id, - 'children': build_tree(dept.id) # 递归构建子部门 + "id": dept.id, + "name": dept.name, + "desc": dept.desc, + "order": dept.order, + "parent_id": dept.parent_id, + "children": build_tree(dept.id), # 递归构建子部门 } - for dept in all_depts if dept.parent_id == parent_id + for dept in all_depts + if dept.parent_id == parent_id ] # 从顶级部门(parent_id=0)开始构建部门树 @@ -36,7 +39,7 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): async def get_dept_info(self): pass - + async def update_dept_closure(self, obj: Dept): parent_depts = await DeptClosure.filter(descendant=obj.parent_id) for i in parent_depts: @@ -44,21 +47,9 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): dept_closure_objs: list[DeptClosure] = [] # 插入父级关系 for item in parent_depts: - dept_closure_objs.append( - DeptClosure( - ancestor=item.ancestor, - descendant=obj.id, - level=item.level + 1 - ) - ) + dept_closure_objs.append(DeptClosure(ancestor=item.ancestor, descendant=obj.id, level=item.level + 1)) # 插入自身x - dept_closure_objs.append( - DeptClosure( - ancestor=obj.id, - descendant=obj.id, - level=0 - ) - ) + dept_closure_objs.append(DeptClosure(ancestor=obj.id, descendant=obj.id, level=0)) # 创建关系 await DeptClosure.bulk_create(dept_closure_objs) @@ -69,7 +60,6 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): await self.get(id=obj_in.parent_id) new_obj = await self.create(obj_in=obj_in) await self.update_dept_closure(new_obj) - @atomic() async def update_dept(self, obj_in: DeptUpdate): @@ -87,9 +77,10 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): async def delete_dept(self, dept_id: int): # 删除部门 obj = await self.get(id=dept_id) - obj.is_deleted = True + obj.is_deleted = True await obj.save() # 删除关系 await DeptClosure.filter(descendant=dept_id).delete() + dept_controller = DeptController() diff --git a/app/core/init_app.py b/app/core/init_app.py index 989438b..99032d8 100644 --- a/app/core/init_app.py +++ b/app/core/init_app.py @@ -1,7 +1,6 @@ from fastapi import FastAPI from fastapi.middleware import Middleware from fastapi.middleware.cors import CORSMiddleware -from tortoise.contrib.fastapi import register_tortoise from app.api import api_router from app.controllers.user import UserCreate, user_controller @@ -38,16 +37,6 @@ def make_middlewares(): return middleware -def register_db(app: FastAPI, db_url=None): - register_tortoise( - app, - # db_url='sqlite://db.sqlite3', - # modules={'models':['app.models', "aerich.models"]}, - config=settings.TORTOISE_ORM, - generate_schemas=True, - ) - - def register_exceptions(app: FastAPI): app.add_exception_handler(DoesNotExist, DoesNotExistHandle) app.add_exception_handler(HTTPException, HttpExcHandle) @@ -169,4 +158,4 @@ async def init_menus(): is_hidden=False, component="/top-menu", keepalive=True, - ) \ No newline at end of file + ) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..180a659 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,74 @@ +aiosqlite==0.17.0 +annotated-types==0.6.0 +anyio==4.3.0 +argon2-cffi==23.1.0 +argon2-cffi-bindings==21.2.0 +black==23.12.1 +blinker==1.7.0 +certifi==2024.2.2 +cffi==1.16.0 +click==8.1.7 +dep-logic==0.2.0 +distlib==0.3.8 +dnspython==2.6.1 +email_validator==2.1.1 +fastapi==0.111.0 +fastapi-cli==0.0.4 +filelock==3.13.4 +findpython==0.6.0 +gunicorn==21.2.0 +h11==0.14.0 +hishel==0.0.26 +httpcore==1.0.5 +httptools==0.6.1 +httpx==0.27.0 +idna==3.7 +installer==0.7.0 +iso8601==1.1.0 +isort==5.13.2 +Jinja2==3.1.4 +loguru==0.7.2 +markdown-it-py==3.0.0 +MarkupSafe==2.1.5 +mdurl==0.1.2 +msgpack==1.0.8 +mypy-extensions==1.0.0 +orjson==3.10.3 +packaging==24.0 +passlib==1.7.4 +pathspec==0.12.1 +pbs-installer==2024.4.1 +pdm==2.14.0 +platformdirs==4.2.2 +pycparser==2.22 +pydantic==2.7.1 +pydantic-settings==2.2.1 +pydantic_core==2.18.2 +Pygments==2.18.0 +PyJWT==2.8.0 +pypika-tortoise==0.1.6 +pyproject_hooks==1.0.0 +python-dotenv==1.0.1 +python-multipart==0.0.9 +pytz==2024.1 +PyYAML==6.0.1 +resolvelib==1.0.1 +rich==13.7.1 +ruff==0.0.281 +shellingham==1.5.4 +sniffio==1.3.1 +socksio==1.0.0 +starlette==0.37.2 +tomlkit==0.12.4 +tortoise-orm==0.20.1 +truststore==0.8.0 +typer==0.12.3 +typing_extensions==4.11.0 +ujson==5.10.0 +unearth==0.15.1 +uvicorn==0.23.2 +uvloop==0.19.0 +virtualenv==20.25.1 +watchfiles==0.21.0 +websockets==12.0 +zstandard==0.22.0