diff --git a/backend/app/admin/crud/crud_api.py b/backend/app/admin/crud/crud_api.py index 723624e0..1175d158 100644 --- a/backend/app/admin/crud/crud_api.py +++ b/backend/app/admin/crud/crud_api.py @@ -4,13 +4,13 @@ from typing import Sequence from sqlalchemy import Select, and_, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import Api from backend.app.admin.schema.api import CreateApiParam, UpdateApiParam -from backend.common.msd.crud import CRUDBase -class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): +class CRUDApi(CRUDPlus[Api]): async def get(self, db: AsyncSession, pk: int) -> Api | None: """ 获取 API @@ -19,7 +19,7 @@ class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): :param pk: :return: """ - return await self.get_(db, pk=pk) + return await self.select_model_by_id(db, pk) async def get_list(self, name: str = None, method: str = None, path: str = None) -> Select: """ @@ -49,8 +49,7 @@ class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): :param db: :return: """ - apis = await db.execute(select(self.model)) - return apis.scalars().all() + return await self.select_models(db) async def get_by_name(self, db: AsyncSession, name: str) -> Api | None: """ @@ -60,8 +59,7 @@ class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): :param name: :return: """ - api = await db.execute(select(self.model).where(self.model.name == name)) - return api.scalars().first() + return await self.select_model_by_column(db, 'name', name) async def create(self, db: AsyncSession, obj_in: CreateApiParam) -> None: """ @@ -71,7 +69,7 @@ class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db: AsyncSession, pk: int, obj_in: UpdateApiParam) -> int: """ @@ -82,7 +80,7 @@ class CRUDApi(CRUDBase[Api, CreateApiParam, UpdateApiParam]): :param obj_in: :return: """ - return await self.update_(db, pk, obj_in) + return await self.update_model(db, pk, obj_in) async def delete(self, db: AsyncSession, pk: list[int]) -> int: """ diff --git a/backend/app/admin/crud/crud_casbin.py b/backend/app/admin/crud/crud_casbin.py index bd8d69bf..81615cce 100644 --- a/backend/app/admin/crud/crud_casbin.py +++ b/backend/app/admin/crud/crud_casbin.py @@ -4,13 +4,13 @@ from uuid import UUID from sqlalchemy import Select, and_, delete, or_, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import CasbinRule -from backend.app.admin.schema.casbin_rule import CreatePolicyParam, DeleteAllPoliciesParam, UpdatePolicyParam -from backend.common.msd.crud import CRUDBase +from backend.app.admin.schema.casbin_rule import DeleteAllPoliciesParam -class CRUDCasbin(CRUDBase[CasbinRule, CreatePolicyParam, UpdatePolicyParam]): +class CRUDCasbin(CRUDPlus[CasbinRule]): async def get_list(self, ptype: str, sub: str) -> Select: """ 获取策略列表 @@ -19,7 +19,7 @@ class CRUDCasbin(CRUDBase[CasbinRule, CreatePolicyParam, UpdatePolicyParam]): :param sub: :return: """ - se = select(self.model).order_by(self.model.id) + se = select(self.model).order_by(self.model.id.desc()) where_list = [] if ptype: where_list.append(self.model.ptype == ptype) diff --git a/backend/app/admin/crud/crud_dept.py b/backend/app/admin/crud/crud_dept.py index 3cd5fd44..db7adf49 100644 --- a/backend/app/admin/crud/crud_dept.py +++ b/backend/app/admin/crud/crud_dept.py @@ -5,13 +5,13 @@ from typing import Sequence from sqlalchemy import and_, asc, or_, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import Dept, User from backend.app.admin.schema.dept import CreateDeptParam, UpdateDeptParam -from backend.common.msd.crud import CRUDBase -class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): +class CRUDDept(CRUDPlus[Dept]): async def get(self, db: AsyncSession, dept_id: int) -> Dept | None: """ 获取部门 @@ -20,7 +20,7 @@ class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): :param dept_id: :return: """ - return await self.get_(db, pk=dept_id, del_flag=0) + return await self.select_model_by_columns(db, id=dept_id, del_flag=0) async def get_by_name(self, db: AsyncSession, name: str) -> Dept | None: """ @@ -30,7 +30,7 @@ class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): :param name: :return: """ - return await self.get_(db, name=name, del_flag=0) + return await self.select_model_by_columns(db, name=name, del_flag=0) async def get_all( self, db: AsyncSession, name: str = None, leader: str = None, phone: str = None, status: int = None @@ -76,7 +76,7 @@ class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db: AsyncSession, dept_id: int, obj_in: UpdateDeptParam) -> int: """ @@ -87,7 +87,7 @@ class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): :param obj_in: :return: """ - return await self.update_(db, dept_id, obj_in) + return await self.update_model(db, dept_id, obj_in) async def delete(self, db: AsyncSession, dept_id: int) -> int: """ @@ -97,7 +97,7 @@ class CRUDDept(CRUDBase[Dept, CreateDeptParam, UpdateDeptParam]): :param dept_id: :return: """ - return await self.delete_(db, dept_id, del_flag=1) + return await self.delete_model(db, dept_id, del_flag=1) async def get_relation(self, db: AsyncSession, dept_id: int) -> list[User]: """ diff --git a/backend/app/admin/crud/crud_dict_data.py b/backend/app/admin/crud/crud_dict_data.py index 4199217d..7a744901 100644 --- a/backend/app/admin/crud/crud_dict_data.py +++ b/backend/app/admin/crud/crud_dict_data.py @@ -3,13 +3,13 @@ from sqlalchemy import Select, and_, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import DictData from backend.app.admin.schema.dict_data import CreateDictDataParam, UpdateDictDataParam -from backend.common.msd.crud import CRUDBase -class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]): +class CRUDDictData(CRUDPlus[DictData]): async def get(self, db: AsyncSession, pk: int) -> DictData | None: """ 获取字典数据 @@ -18,7 +18,7 @@ class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]) :param pk: :return: """ - return await self.get_(db, pk=pk) + return await self.select_model_by_id(db, pk) async def get_list(self, label: str = None, value: str = None, status: int = None) -> Select: """ @@ -49,8 +49,7 @@ class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]) :param label: :return: """ - api = await db.execute(select(self.model).where(self.model.label == label)) - return api.scalars().first() + return await self.select_model_by_column(db, 'label', label) async def create(self, db: AsyncSession, obj_in: CreateDictDataParam) -> None: """ @@ -60,7 +59,7 @@ class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]) :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db: AsyncSession, pk: int, obj_in: UpdateDictDataParam) -> int: """ @@ -71,7 +70,7 @@ class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]) :param obj_in: :return: """ - return await self.update_(db, pk, obj_in) + return await self.update_model(db, pk, obj_in) async def delete(self, db: AsyncSession, pk: list[int]) -> int: """ @@ -92,8 +91,9 @@ class CRUDDictData(CRUDBase[DictData, CreateDictDataParam, UpdateDictDataParam]) :param pk: :return: """ - where = [self.model.id == pk] - dict_data = await db.execute(select(self.model).options(selectinload(self.model.type)).where(*where)) + dict_data = await db.execute( + select(self.model).options(selectinload(self.model.type)).where(self.model.id == pk) + ) return dict_data.scalars().first() diff --git a/backend/app/admin/crud/crud_dict_type.py b/backend/app/admin/crud/crud_dict_type.py index a34af106..18a1739e 100644 --- a/backend/app/admin/crud/crud_dict_type.py +++ b/backend/app/admin/crud/crud_dict_type.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- from sqlalchemy import Select, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import DictType from backend.app.admin.schema.dict_type import CreateDictTypeParam, UpdateDictTypeParam -from backend.common.msd.crud import CRUDBase -class CRUDDictType(CRUDBase[DictType, CreateDictTypeParam, UpdateDictTypeParam]): +class CRUDDictType(CRUDPlus[DictType]): async def get(self, db: AsyncSession, pk: int) -> DictType | None: """ 获取字典类型 @@ -17,7 +17,7 @@ class CRUDDictType(CRUDBase[DictType, CreateDictTypeParam, UpdateDictTypeParam]) :param pk: :return: """ - return await self.get_(db, pk=pk) + return await self.select_model_by_id(db, pk) async def get_list(self, *, name: str = None, code: str = None, status: int = None) -> Select: """ @@ -48,8 +48,7 @@ class CRUDDictType(CRUDBase[DictType, CreateDictTypeParam, UpdateDictTypeParam]) :param code: :return: """ - dept = await db.execute(select(self.model).where(self.model.code == code)) - return dept.scalars().first() + return await self.select_model_by_column(db, 'code', code) async def create(self, db: AsyncSession, obj_in: CreateDictTypeParam) -> None: """ @@ -59,7 +58,7 @@ class CRUDDictType(CRUDBase[DictType, CreateDictTypeParam, UpdateDictTypeParam]) :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db: AsyncSession, pk: int, obj_in: UpdateDictTypeParam) -> int: """ @@ -70,7 +69,7 @@ class CRUDDictType(CRUDBase[DictType, CreateDictTypeParam, UpdateDictTypeParam]) :param obj_in: :return: """ - return await self.update_(db, pk, obj_in) + return await self.update_model(db, pk, obj_in) async def delete(self, db: AsyncSession, pk: list[int]) -> int: """ diff --git a/backend/app/admin/crud/crud_login_log.py b/backend/app/admin/crud/crud_login_log.py index 6e82b2f6..e1ef2e23 100644 --- a/backend/app/admin/crud/crud_login_log.py +++ b/backend/app/admin/crud/crud_login_log.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- from sqlalchemy import Select, and_, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import LoginLog -from backend.app.admin.schema.login_log import CreateLoginLogParam, UpdateLoginLogParam -from backend.common.msd.crud import CRUDBase +from backend.app.admin.schema.login_log import CreateLoginLogParam -class CRUDLoginLog(CRUDBase[LoginLog, CreateLoginLogParam, UpdateLoginLogParam]): +class CRUDLoginLog(CRUDPlus[LoginLog]): async def get_list(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select: """ 获取登录日志列表 @@ -38,7 +38,7 @@ class CRUDLoginLog(CRUDBase[LoginLog, CreateLoginLogParam, UpdateLoginLogParam]) :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) await db.commit() async def delete(self, db: AsyncSession, pk: list[int]) -> int: diff --git a/backend/app/admin/crud/crud_menu.py b/backend/app/admin/crud/crud_menu.py index 5d59a242..a6c4d08a 100644 --- a/backend/app/admin/crud/crud_menu.py +++ b/backend/app/admin/crud/crud_menu.py @@ -4,13 +4,13 @@ from typing import Sequence from sqlalchemy import and_, asc, select from sqlalchemy.orm import selectinload +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import Menu from backend.app.admin.schema.menu import CreateMenuParam, UpdateMenuParam -from backend.common.msd.crud import CRUDBase -class CRUDMenu(CRUDBase[Menu, CreateMenuParam, UpdateMenuParam]): +class CRUDMenu(CRUDPlus[Menu]): async def get(self, db, menu_id: int) -> Menu | None: """ 获取菜单 @@ -19,7 +19,7 @@ class CRUDMenu(CRUDBase[Menu, CreateMenuParam, UpdateMenuParam]): :param menu_id: :return: """ - return await self.get_(db, pk=menu_id) + return await self.select_model_by_id(db, menu_id) async def get_by_title(self, db, title: str) -> Menu | None: """ @@ -77,7 +77,7 @@ class CRUDMenu(CRUDBase[Menu, CreateMenuParam, UpdateMenuParam]): :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db, menu_id: int, obj_in: UpdateMenuParam) -> int: """ @@ -88,7 +88,7 @@ class CRUDMenu(CRUDBase[Menu, CreateMenuParam, UpdateMenuParam]): :param obj_in: :return: """ - count = await self.update_(db, menu_id, obj_in) + count = await self.update_model(db, menu_id, obj_in) return count async def delete(self, db, menu_id: int) -> int: @@ -99,7 +99,7 @@ class CRUDMenu(CRUDBase[Menu, CreateMenuParam, UpdateMenuParam]): :param menu_id: :return: """ - return await self.delete_(db, menu_id) + return await self.delete_model(db, menu_id) async def get_children(self, db, menu_id: int) -> list[Menu]: """ diff --git a/backend/app/admin/crud/crud_opera_log.py b/backend/app/admin/crud/crud_opera_log.py index 45ef61c0..8417cc15 100644 --- a/backend/app/admin/crud/crud_opera_log.py +++ b/backend/app/admin/crud/crud_opera_log.py @@ -2,13 +2,13 @@ # -*- coding: utf-8 -*- from sqlalchemy import Select, and_, delete, desc, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import OperaLog -from backend.app.admin.schema.opera_log import CreateOperaLogParam, UpdateOperaLogParam -from backend.common.msd.crud import CRUDBase +from backend.app.admin.schema.opera_log import CreateOperaLogParam -class CRUDOperaLogDao(CRUDBase[OperaLog, CreateOperaLogParam, UpdateOperaLogParam]): +class CRUDOperaLogDao(CRUDPlus[OperaLog]): async def get_list(self, username: str | None = None, status: int | None = None, ip: str | None = None) -> Select: """ 获取操作日志列表 @@ -38,7 +38,7 @@ class CRUDOperaLogDao(CRUDBase[OperaLog, CreateOperaLogParam, UpdateOperaLogPara :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def delete(self, db: AsyncSession, pk: list[int]) -> int: """ diff --git a/backend/app/admin/crud/crud_role.py b/backend/app/admin/crud/crud_role.py index 0557573c..653aa282 100644 --- a/backend/app/admin/crud/crud_role.py +++ b/backend/app/admin/crud/crud_role.py @@ -4,13 +4,13 @@ from typing import Sequence from sqlalchemy import Select, delete, desc, select from sqlalchemy.orm import selectinload +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import Menu, Role, User from backend.app.admin.schema.role import CreateRoleParam, UpdateRoleMenuParam, UpdateRoleParam -from backend.common.msd.crud import CRUDBase -class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): +class CRUDRole(CRUDPlus[Role]): async def get(self, db, role_id: int) -> Role | None: """ 获取角色 @@ -19,7 +19,7 @@ class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): :param role_id: :return: """ - return await self.get_(db, pk=role_id) + return await self.select_model_by_id(db, role_id) async def get_with_relation(self, db, role_id: int) -> Role | None: """ @@ -41,8 +41,7 @@ class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): :param db: :return: """ - roles = await db.execute(select(self.model)) - return roles.scalars().all() + return await self.select_models(db) async def get_user_roles(self, db, user_id: int) -> Sequence[Role]: """ @@ -84,8 +83,7 @@ class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): :param name: :return: """ - role = await db.execute(select(self.model).where(self.model.name == name)) - return role.scalars().first() + return await self.select_model_by_column(db, 'name', name) async def create(self, db, obj_in: CreateRoleParam) -> None: """ @@ -95,7 +93,7 @@ class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def update(self, db, role_id: int, obj_in: UpdateRoleParam) -> int: """ @@ -106,7 +104,7 @@ class CRUDRole(CRUDBase[Role, CreateRoleParam, UpdateRoleParam]): :param obj_in: :return: """ - rowcount = await self.update_(db, pk=role_id, obj_in=obj_in) + rowcount = await self.update_model(db, role_id, obj_in) return rowcount async def update_menus(self, db, role_id: int, menu_ids: UpdateRoleMenuParam) -> int: diff --git a/backend/app/admin/crud/crud_user.py b/backend/app/admin/crud/crud_user.py index 37be7ca6..17bc43fb 100644 --- a/backend/app/admin/crud/crud_user.py +++ b/backend/app/admin/crud/crud_user.py @@ -5,6 +5,7 @@ from sqlalchemy import and_, desc, select, update from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload from sqlalchemy.sql import Select +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import Role, User from backend.app.admin.schema.user import ( @@ -14,12 +15,11 @@ from backend.app.admin.schema.user import ( UpdateUserParam, UpdateUserRoleParam, ) -from backend.common.msd.crud import CRUDBase from backend.common.security.jwt import get_hash_password from backend.utils.timezone import timezone -class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): +class CRUDUser(CRUDPlus[User]): async def get(self, db: AsyncSession, user_id: int) -> User | None: """ 获取用户 @@ -28,7 +28,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param user_id: :return: """ - return await self.get_(db, pk=user_id) + return await self.select_model_by_id(db, user_id) async def get_by_username(self, db: AsyncSession, username: str) -> User | None: """ @@ -38,8 +38,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param username: :return: """ - user = await db.execute(select(self.model).where(self.model.username == username)) - return user.scalars().first() + return await self.select_model_by_column(db, 'username', username) async def get_by_nickname(self, db: AsyncSession, nickname: str) -> User | None: """ @@ -49,8 +48,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param nickname: :return: """ - user = await db.execute(select(self.model).where(self.model.nickname == nickname)) - return user.scalars().first() + return await self.select_model_by_column(db, 'nickname', nickname) async def update_login_time(self, db: AsyncSession, username: str) -> int: """ @@ -113,8 +111,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param obj: :return: """ - user = await db.execute(update(self.model).where(self.model.id == input_user.id).values(**obj.model_dump())) - return user.rowcount + return await self.update_model(db, input_user.id, obj) @staticmethod async def update_role(db: AsyncSession, input_user: User, obj: UpdateUserRoleParam) -> None: @@ -144,8 +141,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param avatar: :return: """ - user = await db.execute(update(self.model).where(self.model.id == current_user.id).values(avatar=avatar.url)) - return user.rowcount + return await self.update_model(db, current_user.id, {'avatar': avatar.url}) async def delete(self, db: AsyncSession, user_id: int) -> int: """ @@ -155,7 +151,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param user_id: :return: """ - return await self.delete_(db, user_id) + return await self.delete_model(db, user_id) async def check_email(self, db: AsyncSession, email: str) -> User | None: """ @@ -165,8 +161,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param email: :return: """ - mail = await db.execute(select(self.model).where(self.model.email == email)) - return mail.scalars().first() + return await self.select_model_by_column(db, 'email', email) async def reset_password(self, db: AsyncSession, pk: int, password: str, salt: str) -> int: """ @@ -178,10 +173,8 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :param salt: :return: """ - user = await db.execute( - update(self.model).where(self.model.id == pk).values(password=await get_hash_password(password + salt)) - ) - return user.rowcount + new_pwd = await get_hash_password(f'{password}{salt}') + return await self.update_model(db, pk, {'password': new_pwd}) async def get_list(self, dept: int = None, username: str = None, phone: str = None, status: int = None) -> Select: """ @@ -265,10 +258,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :return: """ super_status = await self.get_super(db, user_id) - user = await db.execute( - update(self.model).where(self.model.id == user_id).values(is_superuser=False if super_status else True) - ) - return user.rowcount + return await self.update_model(db, user_id, {'is_superuser': False if super_status else True}) async def set_staff(self, db: AsyncSession, user_id: int) -> int: """ @@ -279,10 +269,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :return: """ staff_status = await self.get_staff(db, user_id) - user = await db.execute( - update(self.model).where(self.model.id == user_id).values(is_staff=False if staff_status else True) - ) - return user.rowcount + return await self.update_model(db, user_id, {'is_staff': False if staff_status else True}) async def set_status(self, db: AsyncSession, user_id: int) -> int: """ @@ -293,10 +280,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :return: """ status = await self.get_status(db, user_id) - user = await db.execute( - update(self.model).where(self.model.id == user_id).values(status=False if status else True) - ) - return user.rowcount + return await self.update_model(db, user_id, {'status': False if status else True}) async def set_multi_login(self, db: AsyncSession, user_id: int) -> int: """ @@ -307,10 +291,7 @@ class CRUDUser(CRUDBase[User, RegisterUserParam, UpdateUserParam]): :return: """ multi_login = await self.get_multi_login(db, user_id) - user = await db.execute( - update(self.model).where(self.model.id == user_id).values(is_multi_login=False if multi_login else True) - ) - return user.rowcount + return await self.update_model(db, user_id, {'is_multi_login': False if multi_login else True}) async def get_with_relation(self, db: AsyncSession, *, user_id: int = None, username: str = None) -> User | None: """ diff --git a/backend/app/admin/crud/crud_user_social.py b/backend/app/admin/crud/crud_user_social.py index 6db10772..8b5defc3 100644 --- a/backend/app/admin/crud/crud_user_social.py +++ b/backend/app/admin/crud/crud_user_social.py @@ -1,15 +1,14 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from sqlalchemy import and_, select from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy_crud_plus import CRUDPlus from backend.app.admin.model import UserSocial -from backend.app.admin.schema.user_social import CreateUserSocialParam, UpdateUserSocialParam +from backend.app.admin.schema.user_social import CreateUserSocialParam from backend.common.enums import UserSocialType -from backend.common.msd.crud import CRUDBase -class CRUDOUserSocial(CRUDBase[UserSocial, CreateUserSocialParam, UpdateUserSocialParam]): +class CRUDOUserSocial(CRUDPlus[UserSocial]): async def get(self, db: AsyncSession, pk: int, source: UserSocialType) -> UserSocial | None: """ 获取用户社交账号绑定 @@ -19,9 +18,7 @@ class CRUDOUserSocial(CRUDBase[UserSocial, CreateUserSocialParam, UpdateUserSoci :param source: :return: """ - se = select(self.model).where(and_(self.model.id == pk, self.model.source == source)) - user_social = await db.execute(se) - return user_social.scalars().first() + return await self.select_model_by_columns(db, id=pk, source=source) async def create(self, db: AsyncSession, obj_in: CreateUserSocialParam) -> None: """ @@ -31,7 +28,7 @@ class CRUDOUserSocial(CRUDBase[UserSocial, CreateUserSocialParam, UpdateUserSoci :param obj_in: :return: """ - await self.create_(db, obj_in) + await self.create_model(db, obj_in) async def delete(self, db: AsyncSession, social_id: int) -> int: """ @@ -41,7 +38,7 @@ class CRUDOUserSocial(CRUDBase[UserSocial, CreateUserSocialParam, UpdateUserSoci :param social_id: :return: """ - return await self.delete_(db, social_id) + return await self.delete_model(db, social_id) user_social_dao: CRUDOUserSocial = CRUDOUserSocial(UserSocial) diff --git a/backend/app/admin/model/__init__.py b/backend/app/admin/model/__init__.py index cec0611f..36028d7e 100644 --- a/backend/app/admin/model/__init__.py +++ b/backend/app/admin/model/__init__.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -from backend.common.msd.model import MappedBase # noqa: I001 +from backend.common.model import MappedBase # noqa: I001 from backend.app.admin.model.sys_api import Api from backend.app.admin.model.sys_casbin_rule import CasbinRule from backend.app.admin.model.sys_dept import Dept diff --git a/backend/app/admin/model/sys_api.py b/backend/app/admin/model/sys_api.py index 101852cd..f4242bbd 100644 --- a/backend/app/admin/model/sys_api.py +++ b/backend/app/admin/model/sys_api.py @@ -4,7 +4,7 @@ from sqlalchemy import String from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class Api(Base): diff --git a/backend/app/admin/model/sys_casbin_rule.py b/backend/app/admin/model/sys_casbin_rule.py index f9e9cbe6..423da141 100644 --- a/backend/app/admin/model/sys_casbin_rule.py +++ b/backend/app/admin/model/sys_casbin_rule.py @@ -4,7 +4,7 @@ from sqlalchemy import String from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.msd.model import MappedBase, id_key +from backend.common.model import MappedBase, id_key class CasbinRule(MappedBase): diff --git a/backend/app/admin/model/sys_dept.py b/backend/app/admin/model/sys_dept.py index 3462fc1a..2e1492e9 100644 --- a/backend/app/admin/model/sys_dept.py +++ b/backend/app/admin/model/sys_dept.py @@ -5,7 +5,7 @@ from typing import Union from sqlalchemy import ForeignKey, String from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class Dept(Base): diff --git a/backend/app/admin/model/sys_dict_data.py b/backend/app/admin/model/sys_dict_data.py index a52cee72..71874768 100644 --- a/backend/app/admin/model/sys_dict_data.py +++ b/backend/app/admin/model/sys_dict_data.py @@ -4,7 +4,7 @@ from sqlalchemy import ForeignKey, String from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class DictData(Base): diff --git a/backend/app/admin/model/sys_dict_type.py b/backend/app/admin/model/sys_dict_type.py index 82f756e8..3190162e 100644 --- a/backend/app/admin/model/sys_dict_type.py +++ b/backend/app/admin/model/sys_dict_type.py @@ -4,7 +4,7 @@ from sqlalchemy import String from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class DictType(Base): diff --git a/backend/app/admin/model/sys_login_log.py b/backend/app/admin/model/sys_login_log.py index 62fbbd8a..a5bd3a33 100644 --- a/backend/app/admin/model/sys_login_log.py +++ b/backend/app/admin/model/sys_login_log.py @@ -6,7 +6,7 @@ from sqlalchemy import String from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.msd.model import DataClassBase, id_key +from backend.common.model import DataClassBase, id_key from backend.utils.timezone import timezone diff --git a/backend/app/admin/model/sys_menu.py b/backend/app/admin/model/sys_menu.py index b1d7ef45..f3233b2c 100644 --- a/backend/app/admin/model/sys_menu.py +++ b/backend/app/admin/model/sys_menu.py @@ -7,7 +7,7 @@ from sqlalchemy.dialects.mysql import LONGTEXT from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.sys_role_menu import sys_role_menu -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class Menu(Base): diff --git a/backend/app/admin/model/sys_opera_log.py b/backend/app/admin/model/sys_opera_log.py index dd84bba6..646266e5 100644 --- a/backend/app/admin/model/sys_opera_log.py +++ b/backend/app/admin/model/sys_opera_log.py @@ -6,7 +6,7 @@ from sqlalchemy import String from sqlalchemy.dialects.mysql import JSON, LONGTEXT from sqlalchemy.orm import Mapped, mapped_column -from backend.common.msd.model import DataClassBase, id_key +from backend.common.model import DataClassBase, id_key from backend.utils.timezone import timezone diff --git a/backend/app/admin/model/sys_role.py b/backend/app/admin/model/sys_role.py index f9d59384..acf46c01 100644 --- a/backend/app/admin/model/sys_role.py +++ b/backend/app/admin/model/sys_role.py @@ -6,7 +6,7 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.sys_role_menu import sys_role_menu from backend.app.admin.model.sys_user_role import sys_user_role -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class Role(Base): diff --git a/backend/app/admin/model/sys_role_menu.py b/backend/app/admin/model/sys_role_menu.py index cde1c770..e1f2cb7d 100644 --- a/backend/app/admin/model/sys_role_menu.py +++ b/backend/app/admin/model/sys_role_menu.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from sqlalchemy import INT, Column, ForeignKey, Integer, Table -from backend.common.msd.model import MappedBase +from backend.common.model import MappedBase sys_role_menu = Table( 'sys_role_menu', diff --git a/backend/app/admin/model/sys_user.py b/backend/app/admin/model/sys_user.py index 19055d07..dab80193 100644 --- a/backend/app/admin/model/sys_user.py +++ b/backend/app/admin/model/sys_user.py @@ -7,7 +7,7 @@ from sqlalchemy import ForeignKey, String from sqlalchemy.orm import Mapped, mapped_column, relationship from backend.app.admin.model.sys_user_role import sys_user_role -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key from backend.database.db_mysql import uuid4_str from backend.utils.timezone import timezone diff --git a/backend/app/admin/model/sys_user_role.py b/backend/app/admin/model/sys_user_role.py index 88c41de6..1870360e 100644 --- a/backend/app/admin/model/sys_user_role.py +++ b/backend/app/admin/model/sys_user_role.py @@ -2,7 +2,7 @@ # -*- coding: utf-8 -*- from sqlalchemy import INT, Column, ForeignKey, Integer, Table -from backend.common.msd.model import MappedBase +from backend.common.model import MappedBase sys_user_role = Table( 'sys_user_role', diff --git a/backend/app/admin/model/sys_user_social.py b/backend/app/admin/model/sys_user_social.py index 3389cf7c..42c8833a 100644 --- a/backend/app/admin/model/sys_user_social.py +++ b/backend/app/admin/model/sys_user_social.py @@ -5,7 +5,7 @@ from typing import Union from sqlalchemy import ForeignKey, String from sqlalchemy.orm import Mapped, mapped_column, relationship -from backend.common.msd.model import Base, id_key +from backend.common.model import Base, id_key class UserSocial(Base): diff --git a/backend/app/admin/schema/api.py b/backend/app/admin/schema/api.py index 979d6078..cb13bbb2 100644 --- a/backend/app/admin/schema/api.py +++ b/backend/app/admin/schema/api.py @@ -5,7 +5,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.enums import MethodType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class ApiSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/casbin_rule.py b/backend/app/admin/schema/casbin_rule.py index 5ece8a96..7eae20cc 100644 --- a/backend/app/admin/schema/casbin_rule.py +++ b/backend/app/admin/schema/casbin_rule.py @@ -3,7 +3,7 @@ from pydantic import ConfigDict, Field from backend.common.enums import MethodType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class CreatePolicyParam(SchemaBase): diff --git a/backend/app/admin/schema/dept.py b/backend/app/admin/schema/dept.py index 63899277..fac9f89d 100644 --- a/backend/app/admin/schema/dept.py +++ b/backend/app/admin/schema/dept.py @@ -5,7 +5,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.enums import StatusType -from backend.common.msd.schema import CustomEmailStr, CustomPhoneNumber, SchemaBase +from backend.common.schema import CustomEmailStr, CustomPhoneNumber, SchemaBase class DeptSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/dict_data.py b/backend/app/admin/schema/dict_data.py index 179ba5d7..d3b4afb4 100644 --- a/backend/app/admin/schema/dict_data.py +++ b/backend/app/admin/schema/dict_data.py @@ -6,7 +6,7 @@ from pydantic import ConfigDict, Field from backend.app.admin.schema.dict_type import GetDictTypeListDetails from backend.common.enums import StatusType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class DictDataSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/dict_type.py b/backend/app/admin/schema/dict_type.py index 61edfc9c..ea7ea3e6 100644 --- a/backend/app/admin/schema/dict_type.py +++ b/backend/app/admin/schema/dict_type.py @@ -5,7 +5,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.enums import StatusType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class DictTypeSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/login_log.py b/backend/app/admin/schema/login_log.py index 14e59f85..f134ef2f 100644 --- a/backend/app/admin/schema/login_log.py +++ b/backend/app/admin/schema/login_log.py @@ -4,7 +4,7 @@ from datetime import datetime from pydantic import ConfigDict -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class LoginLogSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/menu.py b/backend/app/admin/schema/menu.py index a69802cd..e095924e 100644 --- a/backend/app/admin/schema/menu.py +++ b/backend/app/admin/schema/menu.py @@ -5,7 +5,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.enums import MenuType, StatusType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class MenuSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/opera_log.py b/backend/app/admin/schema/opera_log.py index 50ccc468..6ad3a591 100644 --- a/backend/app/admin/schema/opera_log.py +++ b/backend/app/admin/schema/opera_log.py @@ -5,7 +5,7 @@ from datetime import datetime from pydantic import ConfigDict, Field from backend.common.enums import StatusType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class OperaLogSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/role.py b/backend/app/admin/schema/role.py index 8901c7ff..e1fd61ef 100644 --- a/backend/app/admin/schema/role.py +++ b/backend/app/admin/schema/role.py @@ -6,7 +6,7 @@ from pydantic import ConfigDict, Field from backend.app.admin.schema.menu import GetMenuListDetails from backend.common.enums import RoleDataScopeType, StatusType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class RoleSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/token.py b/backend/app/admin/schema/token.py index 2faf7779..efd0c768 100644 --- a/backend/app/admin/schema/token.py +++ b/backend/app/admin/schema/token.py @@ -3,7 +3,7 @@ from datetime import datetime from backend.app.admin.schema.user import GetUserInfoNoRelationDetail -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class GetSwaggerToken(SchemaBase): diff --git a/backend/app/admin/schema/user.py b/backend/app/admin/schema/user.py index ddb03abd..81f45200 100644 --- a/backend/app/admin/schema/user.py +++ b/backend/app/admin/schema/user.py @@ -7,7 +7,7 @@ from pydantic import ConfigDict, EmailStr, Field, HttpUrl, model_validator from backend.app.admin.schema.dept import GetDeptListDetails from backend.app.admin.schema.role import GetRoleListDetails from backend.common.enums import StatusType -from backend.common.msd.schema import CustomPhoneNumber, SchemaBase +from backend.common.schema import CustomPhoneNumber, SchemaBase class AuthSchemaBase(SchemaBase): diff --git a/backend/app/admin/schema/user_social.py b/backend/app/admin/schema/user_social.py index a71b4f1c..464d150f 100644 --- a/backend/app/admin/schema/user_social.py +++ b/backend/app/admin/schema/user_social.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- from backend.common.enums import UserSocialType -from backend.common.msd.schema import SchemaBase +from backend.common.schema import SchemaBase class UserSocialSchemaBase(SchemaBase): diff --git a/backend/common/exception/exception_handler.py b/backend/common/exception/exception_handler.py index 75f869ad..2dd2ef55 100644 --- a/backend/common/exception/exception_handler.py +++ b/backend/common/exception/exception_handler.py @@ -11,12 +11,12 @@ from uvicorn.protocols.http.h11_impl import STATUS_PHRASES from backend.common.exception.errors import BaseExceptionMixin from backend.common.log import log -from backend.common.msd.schema import ( +from backend.common.response.response_code import CustomResponseCode, StandardResponseCode +from backend.common.response.response_schema import response_base +from backend.common.schema import ( CUSTOM_USAGE_ERROR_MESSAGES, CUSTOM_VALIDATION_ERROR_MESSAGES, ) -from backend.common.response.response_code import CustomResponseCode, StandardResponseCode -from backend.common.response.response_schema import response_base from backend.core.conf import settings from backend.utils.serializers import MsgSpecJSONResponse diff --git a/backend/common/msd/model.py b/backend/common/model.py similarity index 100% rename from backend/common/msd/model.py rename to backend/common/model.py diff --git a/backend/common/msd/__init__.py b/backend/common/msd/__init__.py deleted file mode 100644 index 56fafa58..00000000 --- a/backend/common/msd/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- diff --git a/backend/common/msd/crud.py b/backend/common/msd/crud.py deleted file mode 100644 index 8135080b..00000000 --- a/backend/common/msd/crud.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -from typing import Any, Dict, Generic, Type, TypeVar - -from pydantic import BaseModel -from sqlalchemy import and_, delete, select, update -from sqlalchemy.ext.asyncio import AsyncSession - -from backend.common.msd.model import MappedBase - -ModelType = TypeVar('ModelType', bound=MappedBase) -CreateSchemaType = TypeVar('CreateSchemaType', bound=BaseModel) -UpdateSchemaType = TypeVar('UpdateSchemaType', bound=BaseModel) - - -class CRUDBase(Generic[ModelType, CreateSchemaType, UpdateSchemaType]): - def __init__(self, model: Type[ModelType]): - self.model = model - - async def get_( - self, - db: AsyncSession, - *, - pk: int | None = None, - name: str | None = None, - status: int | None = None, - del_flag: int | None = None, - ) -> ModelType | None: - """ - 通过主键 id 或者 name 获取一条数据 - - :param db: - :param pk: - :param name: - :param status: - :param del_flag: - :return: - """ - assert pk is not None or name is not None, '查询错误, pk 和 name 参数不能同时为空' - assert pk is None or name is None, '查询错误, pk 和 name 参数不能同时存在' - where_list = [self.model.id == pk] if pk is not None else [self.model.name == name] - if status is not None: - assert status in (0, 1), '查询错误, status 参数只能为 0 或 1' - where_list.append(self.model.status == status) - if del_flag is not None: - assert del_flag in (0, 1), '查询错误, del_flag 参数只能为 0 或 1' - where_list.append(self.model.del_flag == del_flag) - - result = await db.execute(select(self.model).where(and_(*where_list))) - return result.scalars().first() - - async def create_(self, db: AsyncSession, obj_in: CreateSchemaType, user_id: int | None = None) -> None: - """ - 新增一条数据 - - :param db: - :param obj_in: Pydantic 模型类 - :param user_id: - :return: - """ - if user_id: - create_data = self.model(**obj_in.model_dump(), create_user=user_id) - else: - create_data = self.model(**obj_in.model_dump()) - db.add(create_data) - - async def update_( - self, db: AsyncSession, pk: int, obj_in: UpdateSchemaType | Dict[str, Any], user_id: int | None = None - ) -> int: - """ - 通过主键 id 更新一条数据 - - :param db: - :param pk: - :param obj_in: Pydantic模型类 or 对应数据库字段的字典 - :param user_id: - :return: - """ - if isinstance(obj_in, dict): - update_data = obj_in - else: - update_data = obj_in.model_dump(exclude_unset=True) - if user_id: - update_data.update({'update_user': user_id}) - result = await db.execute(update(self.model).where(self.model.id == pk).values(**update_data)) - return result.rowcount - - async def delete_(self, db: AsyncSession, pk: int, *, del_flag: int | None = None) -> int: - """ - 通过主键 id 删除一条数据 - - :param db: - :param pk: - :param del_flag: - :return: - """ - if del_flag is None: - result = await db.execute(delete(self.model).where(self.model.id == pk)) - else: - assert del_flag == 1, '删除错误, del_flag 参数只能为 1' - result = await db.execute(update(self.model).where(self.model.id == pk).values(del_flag=del_flag)) - return result.rowcount diff --git a/backend/common/msd/schema.py b/backend/common/schema.py similarity index 100% rename from backend/common/msd/schema.py rename to backend/common/schema.py diff --git a/backend/database/db_mysql.py b/backend/database/db_mysql.py index 9a7a9cbd..c5a2e643 100644 --- a/backend/database/db_mysql.py +++ b/backend/database/db_mysql.py @@ -10,7 +10,7 @@ from sqlalchemy import URL from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker, create_async_engine from backend.common.log import log -from backend.common.msd.model import MappedBase +from backend.common.model import MappedBase from backend.core.conf import settings diff --git a/backend/pdm.lock b/backend/pdm.lock index 59e17220..5bde33ed 100644 --- a/backend/pdm.lock +++ b/backend/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "lint", "deploy"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:1e8b094727ea68450c56c0182cfb4ca42ca2347cea93fffd883feac54a5fe44f" +content_hash = "sha256:b67b86e4bf27c72aa5b06f77e3eec479a555c5ba560d82ca8d23a8b98edc901d" [[package]] name = "aiofiles" @@ -1627,6 +1627,21 @@ files = [ {file = "SQLAlchemy-2.0.23.tar.gz", hash = "sha256:c1bda93cbbe4aa2aa0aa8655c5aeda505cd219ff3e8da91d1d329e143e4aff69"}, ] +[[package]] +name = "sqlalchemy-crud-plus" +version = "0.0.2" +requires_python = ">=3.10" +summary = "Asynchronous CRUD operation based on SQLAlchemy2 model" +groups = ["default"] +dependencies = [ + "pydantic>=2.0", + "sqlalchemy>=2.0.0", +] +files = [ + {file = "sqlalchemy_crud_plus-0.0.2-py3-none-any.whl", hash = "sha256:e4f297e000f6e125f26f2c85b9284b6509433aef4e54bb8eab1c624aee019664"}, + {file = "sqlalchemy_crud_plus-0.0.2.tar.gz", hash = "sha256:7dacada2c79204b113a9c8fc4bcf4797bfcb245604c1171b27e87d6ad9e4bb9a"}, +] + [[package]] name = "starlette" version = "0.32.0.post1" diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 9b09ebc2..7a3608c9 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -46,6 +46,7 @@ dependencies = [ "XdbSearchIP==1.0.2", "fastapi_oauth20>=0.0.1a1", "flower==2.0.1", + "sqlalchemy-crud-plus==0.0.2", ] requires-python = ">=3.10" readme = "README.md" diff --git a/backend/requirements.txt b/backend/requirements.txt index 1f13ab1d..4044bc22 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -92,6 +92,7 @@ simpleeval==0.9.13 six==1.16.0 sniffio==1.3.1 sqlalchemy==2.0.23 +sqlalchemy-crud-plus==0.0.2 starlette==0.32.0.post1 supervisor==4.2.5 tomli==2.0.1; python_version < "3.11"