sqlalchemy异步方法使用

建立模型

  1. 创建基类base.py

    python 复制代码
    from sqlalchemy.orm import DeclarativeBase
    
    class Base(DeclarativeBase):
        pass
  2. 以用户为例,建立用户模型继承基类

    python 复制代码
    from sqlalchemy import Integer, String, ForeignKey, DateTime, Boolean
    from sqlalchemy.orm import mapped_column, Mapped
    
    from src.db.model.base import Base
    
    # 用户表
    class User(Base):
        __tablename__ = 'user'
        id: Mapped[int] = mapped_column(Integer, primary_key=True, comment='用户id')
        username: Mapped[str] = mapped_column(String(64), unique=True, nullable=True, comment='用户名称')
        password: Mapped[str] = mapped_column(String(64), comment='用户密码')
        name: Mapped[str] = mapped_column(String(32), comment='姓名')
        mobile_phone: Mapped[str] = mapped_column(String(32), comment='手机号')
        cloud_role_id: Mapped[int] = mapped_column(Integer, ForeignKey('cloud_role.id'), comment='平台角色id')
        user_group_id: Mapped[int] = mapped_column(Integer, ForeignKey('user_group.id'), comment='所在用户组id')
        status: Mapped[Boolean] = mapped_column(Boolean, comment='状态')
        register_time: Mapped[str] = mapped_column(String(32), comment='注册时间')
        last_login_time: Mapped[str] = mapped_column(DateTime, comment='最后登录时间')
    
        __table_args__ = ({'comment': '用户表'})

    comment表示注释,生产mysql的数据表里面会带上注释

  3. 建立异步引擎和session,后面接口的async_session()都从这里引入

    python 复制代码
    from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
    
    engine = create_async_engine(DATABASE_URL, future=True, pool_pre_ping=True, pool_recycle=3600)
    async_session = sessionmaker(engine, expire_on_commit=False, class_=AsyncSession)

编写异步接口

  1. 添加用户

    python 复制代码
    class UserDao:
        def __init__(self):
            pass
    
       @classmethod
        async def add_user(cls, username: str, password: str, name: str, mobile_phone: Optional[str], cloud_role_id: int,
                           user_group_id: int, status: int) -> bool:
            if mobile_phone is None:
                mobile_phone = ''
            # 对密码进行hash
            md_password = hashlib.md5(password.encode('utf-8')).hexdigest()
            user = User(username=username, password=md_password, name=name,
                        mobile_phone=mobile_phone, cloud_role_id=cloud_role_id, user_group_id=user_group_id, status=status)
            user.register_time = datetime.datetime.now()
            user.last_login_time = user.register_time
            
    		# 使用with包裹可以自动处理session的commit()和rollback()
            async with async_session() as session:
                async with session.begin():
                    try:
                        session.add(user)
                        await session.flush()
                        return True
                    except Exception as e:
                        log.error(e)
                        return False
  2. 删除用户

    python 复制代码
        @classmethod
        async def delete_user(cls, user_id: int) -> bool:
            async with async_session() as session:
                async with session.begin():
                    try:
                        query_sql = select(User).filter(User.id == user_id)
                        user = (await session.execute(query_sql)).scalar()
                        if user is not None:
                            # 删除站点关联的用户记录
                            delete_relation_sql = delete(StationSiteUsers).filter(StationSiteUsers.user_id == user_id)
                            await session.execute(delete_relation_sql)
                            # 删除用户
                            delete_user_sql = delete(User).filter(User.id == user_id)
                            await session.execute(delete_user_sql)
                            return True
                        else:
                            return False
                    except Exception as e:
                        log.error(e)
                        return False

    注意,使用select查询时获取单个要用scalar(),因为sqlalchemy的异步方法不支持query。

    一般是select搭配scalar()使用,query()搭配fisrt()使用

  3. 编辑用户

    python 复制代码
        @classmethod
        async def edit_user(cls, user_id: int, username: str, name: str, mobile_phone: Optional[str],
                            cloud_role_id: int, user_group_id: int, status: int) -> bool:
            if mobile_phone is None:
                mobile_phone = ''
            async with async_session() as session:
                async with session.begin():
                    try:
                        # 查询user
                        query_sql = select(User).filter(User.id == user_id)
                        user = (await session.execute(query_sql)).scalar()
                        if user is not None:
                            user.username = username
                            user.name = name
                            user.mobile_phone = mobile_phone
                            user.cloud_role_id = cloud_role_id
                            user.user_group_id = user_group_id
                            user.status = status
                            return True
                        else:
                            return False
                    except Exception as e:
                        log.error(e)
                        return False
  4. 查询用户信息

    python 复制代码
        # 获取所有用户信息
        @classmethod
        async def get_all_user_info(cls) -> List[dict]:
            async with async_session() as session:
                async with session.begin():
                    try:
                        query_sql = select(User.id, User.username, User.name, User.mobile_phone, User.cloud_role_id,
                                           User.status, User.user_group_id, UserGroup.group_name,
                                           User.last_login_time).join(
                            CloudRole, User.cloud_role_id == CloudRole.id).join(
                            UserGroup, User.user_group_id == UserGroup.id)
                        results = (await session.execute(query_sql)).fetchall()
                        user_info_list = []
                        for result in results:
                            user_dict = {'user_id': result[0], 'username': result[1], 'name': result[2],
                                         'mobile_phone': result[3],
                                         'cloud_role_id': result[4], 'status': result[5], 'user_group_id': result[6],
                                         'user_group_name': result[7],
                                         'last_login_time': datetime.datetime.strftime(result[8], '%Y-%m-%d %H:%M:%S')}
                            user_info_list.append(user_dict)
                        return user_info_list
                    except Exception as e:
                        log.error(e)
                        return []

使用pytest编写单元测试

  1. 测试user方法

    python 复制代码
    import pytest
    
    from src.db.async_controller.config import engine
    from src.db.async_dao.user_dao import UserDao
    
    user_dao = UserDao()
    
    
    class TestUserDao:
        def setup_method(self):
            pass
    
        def teardown_method(self):
            engine.dispose()
    
        @pytest.mark.asyncio
        async def test_add_user(self):
            await user_dao.add_user(username='superadmin', password="superadmin", name="superadmin",
                                    mobile_phone="123456", cloud_role_id=1, user_group_id=1, status=1)
            await user_dao.add_user(username='cdy', password="888888", name="cdy",
                                    mobile_phone="123456", cloud_role_id=2, user_group_id=2, status=1)
            # 管理员账号
            await user_dao.add_user(username='admin', password="888888", name="admin",
                                    mobile_phone="123456", cloud_role_id=1, user_group_id=3, status=1)
            await user_dao.add_user(username='admin1', password="888888", name="admin",
                                    mobile_phone="123456", cloud_role_id=1, user_group_id=3, status=1)
            await user_dao.add_user(username='admin2', password="888888", name="admin",
                                    mobile_phone="123456", cloud_role_id=1, user_group_id=3, status=1)
            # 普通账号
            await user_dao.add_user(username='hongdou1', password="888888", name="test",
                                    mobile_phone="123456", cloud_role_id=2, user_group_id=4, status=1)
            await user_dao.add_user(username='hongdou2', password="123456", name="test",
                                    mobile_phone="123456", cloud_role_id=2, user_group_id=4, status=1)
            await user_dao.add_user(username='hongdou3', password="123456", name="test",
                                    mobile_phone="123456", cloud_role_id=2, user_group_id=4, status=1)
            await user_dao.add_user(username='hongdou4', password="123456", name="test",
                                    mobile_phone="123456", cloud_role_id=2, user_group_id=4, status=1)
    
        @pytest.mark.asyncio
        async def test_delete_user(self):
            result = await user_dao.delete_user(user_id=7)
            print(result)
    
        @pytest.mark.asyncio
        async def test_get_accessible_user_list(self):
            print(await user_dao.get_accessible_user_list(user_id=1))
相关推荐
Yanjun2i2 分钟前
Agent学习记录四:多工具时如何处理
人工智能·python·学习·agent
李少兄16 分钟前
Java 中只有值传递吗?
java·开发语言·python
名字还没想好☜28 分钟前
Spring @EventListener 事件驱动解耦实战:同步转异步、事务绑定与顺序控制
java·数据库·后端·python·spring
IT大白鼠1 小时前
MySQL 分布式集群系列 · 第八篇(收官)——NDB 集群面试高频题 +架构总结与未来演进
分布式·mysql·面试
IT大白鼠1 小时前
MySQL 分布式集群系列 · 第七篇——生产调优实战:NDB 性能、内存、高可用全方位优化
数据库·分布式·mysql
ellenwan20261 小时前
看到“最新 AI 量化学习”时,先让表达变清楚
人工智能·python
ShineWinsu1 小时前
对于MySQL:内置函数的解析
linux·数据库·c++·mysql·面试·函数·查询
海宇数据2 小时前
零信任架构实战:基于海宇柠檬查出险-登记证构建自动化残值评估网关
人工智能·python·架构·自动化
李可以量化2 小时前
Tornado 如何增加网页操作(下)
python
zhangzeyuaaa3 小时前
深入理解 pip install .:安装当前目录项目的正确姿势
人工智能·python·pip