commit
2851c32b7c
@ -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()
|
|
||||||
|
|||||||
@ -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()
|
||||||
|
|
||||||
|
|||||||
@ -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="页码"),
|
||||||
|
|||||||
@ -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()
|
||||||
@ -46,4 +45,4 @@ async def delete_dept(
|
|||||||
dept_id: int = Query(..., description="部门ID"),
|
dept_id: int = Query(..., description="部门ID"),
|
||||||
):
|
):
|
||||||
await dept_controller.delete_dept(dept_id=dept_id)
|
await dept_controller.delete_dept(dept_id=dept_id)
|
||||||
return Success(msg="Deleted Success")
|
return Success(msg="Deleted Success")
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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)开始构建部门树
|
||||||
@ -36,7 +39,7 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
|
|||||||
|
|
||||||
async def get_dept_info(self):
|
async def get_dept_info(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
async def update_dept_closure(self, obj: Dept):
|
async def update_dept_closure(self, obj: Dept):
|
||||||
parent_depts = await DeptClosure.filter(descendant=obj.parent_id)
|
parent_depts = await DeptClosure.filter(descendant=obj.parent_id)
|
||||||
for i in parent_depts:
|
for i in parent_depts:
|
||||||
@ -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)
|
||||||
|
|
||||||
@ -69,7 +60,6 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
|
|||||||
await self.get(id=obj_in.parent_id)
|
await self.get(id=obj_in.parent_id)
|
||||||
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):
|
||||||
@ -87,9 +77,10 @@ class DeptController(CRUDBase[Dept, DeptCreate, DeptUpdate]):
|
|||||||
async def delete_dept(self, dept_id: int):
|
async def delete_dept(self, dept_id: int):
|
||||||
# 删除部门
|
# 删除部门
|
||||||
obj = await self.get(id=dept_id)
|
obj = await self.get(id=dept_id)
|
||||||
obj.is_deleted = True
|
obj.is_deleted = True
|
||||||
await obj.save()
|
await obj.save()
|
||||||
# 删除关系
|
# 删除关系
|
||||||
await DeptClosure.filter(descendant=dept_id).delete()
|
await DeptClosure.filter(descendant=dept_id).delete()
|
||||||
|
|
||||||
|
|
||||||
dept_controller = DeptController()
|
dept_controller = DeptController()
|
||||||
|
|||||||
@ -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)
|
||||||
@ -169,4 +158,4 @@ async def init_menus():
|
|||||||
is_hidden=False,
|
is_hidden=False,
|
||||||
component="/top-menu",
|
component="/top-menu",
|
||||||
keepalive=True,
|
keepalive=True,
|
||||||
)
|
)
|
||||||
|
|||||||
74
requirements.txt
Normal file
74
requirements.txt
Normal 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
|
||||||
Loading…
x
Reference in New Issue
Block a user