This commit is contained in:
mizhexiaoxiao 2024-06-06 15:19:18 +08:00
parent 0ee84fad87
commit 279ca78340
8 changed files with 113 additions and 53 deletions

View File

@ -1,11 +1,13 @@
from contextlib import asynccontextmanager
from fastapi import FastAPI from fastapi import FastAPI
from tortoise import Tortoise
from app.core.exceptions import SettingNotFound from app.core.exceptions import SettingNotFound
from app.core.init_app import ( from app.core.init_app import (
init_menus, init_menus,
init_superuser, init_superuser,
make_middlewares, make_middlewares,
register_db,
register_exceptions, register_exceptions,
register_routers, register_routers,
) )
@ -16,6 +18,16 @@ except ImportError:
raise SettingNotFound("Can not import settings") 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: def create_app() -> FastAPI:
app = FastAPI( app = FastAPI(
title=settings.APP_TITLE, title=settings.APP_TITLE,
@ -23,17 +35,11 @@ def create_app() -> FastAPI:
version=settings.VERSION, version=settings.VERSION,
openapi_url="/openapi.json", openapi_url="/openapi.json",
middleware=make_middlewares(), middleware=make_middlewares(),
lifespan=lifespan,
) )
register_db(app)
register_exceptions(app) register_exceptions(app)
register_routers(app, prefix="/api") register_routers(app, prefix="/api")
return app return app
app = create_app() app = create_app()
@app.on_event("startup")
async def startup_event():
await init_superuser()
await init_menus()

View File

@ -4,10 +4,10 @@ from app.core.dependency import DependPermisson
from .apis import apis_router from .apis import apis_router
from .base import base_router from .base import base_router
from .depts import depts_router
from .menus import menus_router from .menus import menus_router
from .roles import roles_router from .roles import roles_router
from .users import users_router from .users import users_router
from .depts import depts_router
v1_router = APIRouter() v1_router = APIRouter()

View File

@ -10,6 +10,7 @@ from app.schemas.apis import *
router = APIRouter() router = APIRouter()
@router.get("/list", summary="查看API列表") @router.get("/list", summary="查看API列表")
async def list_api( async def list_api(
page: int = Query(1, description="页码"), page: int = Query(1, description="页码"),

View File

@ -1,8 +1,7 @@
from fastapi import APIRouter, Query from fastapi import APIRouter, Query
from app.controllers.dept import dept_controller from app.controllers.dept import dept_controller
from app.log import logger from app.schemas import Success
from app.schemas import Success, SuccessExtra
from app.schemas.depts import * from app.schemas.depts import *
router = APIRouter() router = APIRouter()

View File

@ -4,10 +4,10 @@ from fastapi import APIRouter, Query
from fastapi.exceptions import HTTPException from fastapi.exceptions import HTTPException
from tortoise.expressions import Q from tortoise.expressions import Q
from app.controllers.dept import dept_controller
from app.controllers.user import UserController from app.controllers.user import UserController
from app.schemas.base import Success, SuccessExtra from app.schemas.base import Success, SuccessExtra
from app.schemas.users import * from app.schemas.users import *
from app.controllers.dept import dept_controller
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -20,7 +20,7 @@ async def list_user(
page_size: int = Query(10, description="每页数量"), page_size: int = Query(10, description="每页数量"),
username: str = Query("", description="用户名称,用于搜索"), username: str = Query("", description="用户名称,用于搜索"),
email: str = Query("", description="邮箱地址"), email: str = Query("", description="邮箱地址"),
dept_id: int = Query(None, description="部门ID") dept_id: int = Query(None, description="部门ID"),
): ):
user_controller = UserController() user_controller = UserController()
q = Q() q = Q()

View File

@ -1,8 +1,9 @@
from tortoise.expressions import Q
from tortoise.transactions import atomic
from app.core.crud import CRUDBase from app.core.crud import CRUDBase
from app.models.admin import Dept, DeptClosure from app.models.admin import Dept, DeptClosure
from app.schemas.depts import DeptCreate, DeptUpdate from app.schemas.depts import DeptCreate, DeptUpdate
from tortoise.transactions import atomic
from tortoise.expressions import Q
class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]): class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
@ -15,19 +16,21 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
q &= Q(is_deleted=False) q &= Q(is_deleted=False)
if name: if name:
q &= Q(name__contains=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): def build_tree(parent_id):
return [ return [
{ {
'id': dept.id, "id": dept.id,
'name': dept.name, "name": dept.name,
'desc': dept.desc, "desc": dept.desc,
'order': dept.order, "order": dept.order,
'parent_id': dept.parent_id, "parent_id": dept.parent_id,
'children': build_tree(dept.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开始构建部门树 # 从顶级部门parent_id=0开始构建部门树
@ -44,21 +47,9 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
dept_closure_objs: list[DeptClosure] = [] dept_closure_objs: list[DeptClosure] = []
# 插入父级关系 # 插入父级关系
for item in parent_depts: for item in parent_depts:
dept_closure_objs.append( dept_closure_objs.append(DeptClosure(ancestor=item.ancestor, descendant=obj.id, level=item.level + 1))
DeptClosure(
ancestor=item.ancestor,
descendant=obj.id,
level=item.level + 1
)
)
# 插入自身x # 插入自身x
dept_closure_objs.append( dept_closure_objs.append(DeptClosure(ancestor=obj.id, descendant=obj.id, level=0))
DeptClosure(
ancestor=obj.id,
descendant=obj.id,
level=0
)
)
# 创建关系 # 创建关系
await DeptClosure.bulk_create(dept_closure_objs) await DeptClosure.bulk_create(dept_closure_objs)
@ -70,7 +61,6 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
new_obj = await self.create(obj_in=obj_in) new_obj = await self.create(obj_in=obj_in)
await self.update_dept_closure(new_obj) await self.update_dept_closure(new_obj)
@atomic() @atomic()
async def update_dept(self, obj_in: DeptUpdate): async def update_dept(self, obj_in: DeptUpdate):
dept_obj = await self.get(id=obj_in.id) dept_obj = await self.get(id=obj_in.id)
@ -92,4 +82,5 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
# 删除关系 # 删除关系
await DeptClosure.filter(descendant=dept_id).delete() await DeptClosure.filter(descendant=dept_id).delete()
dept_controller = DeptController() dept_controller = DeptController()

View File

@ -1,7 +1,6 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware import Middleware from fastapi.middleware import Middleware
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from tortoise.contrib.fastapi import register_tortoise
from app.api import api_router from app.api import api_router
from app.controllers.user import UserCreate, user_controller from app.controllers.user import UserCreate, user_controller
@ -38,16 +37,6 @@ def make_middlewares():
return middleware 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): def register_exceptions(app: FastAPI):
app.add_exception_handler(DoesNotExist, DoesNotExistHandle) app.add_exception_handler(DoesNotExist, DoesNotExistHandle)
app.add_exception_handler(HTTPException, HttpExcHandle) app.add_exception_handler(HTTPException, HttpExcHandle)

74
requirements.txt Normal file
View File

@ -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