PyQt5 使用 SQLAlchemy 实现用户数据库管理

使用 PyQt5(PySide2)+SQLAlchemy 做一个登录注册页(三)

本文将介绍自己用 PyQt5+SQLAlchemy 做的一个登录注册页,使用邮箱接收验证码本文介绍是前后端未分离的实现方式,后续将出一个前后端分离的,你可以将 PyQt5 改为 PySide2 以获得更宽松的开源协议

本文由于涉及到的代码较多,将会是一个系列,会有多篇文章

系列文章索引

  1. 设计登录注册页面
  2. 添加代码运行登录注册页,并为其添加一些样式,和调用资源文件
  3. 使用 SQLAlchemy 实现用户数据库管理
  4. 为登录页,添加登录逻辑代码,实现登录
  5. 给注册页,添加注册逻辑代码,实现用户的注册验证
  6. 给忘记密码页,添加逻辑,实现密码找回
  7. 给登录添加记住用户密码功能,并优化一些内容

必要说明

  • 使用的环境 requirements.txt
# Python3.8.10 x32
# Windows10 x64
PyQt5
pyqt5-tools
PyMySQL~=1.1.0
sqlalchemy~=2.0.25
bcrypt~=4.1.2
  • 项目结构(显示变化的部分)
--- QtLoginRegistration
  |--- db
     |--- __init__.py
     |--- models.py        # 数据模型
  |--- setting.py          # 设置

使用 SQLAlchemy 实现用户数据库管理

第1步

新建setting.py 文件,统一存放设置项目

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : QtLoginRegistration 
@ File        : setting.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 
"""
import os


# 使用方法:若需要修改默认参数,则直接在子类中用相同参数名称重新设置即可
# 需要配置的环境变量:EMAIL_PASSWORD,DB_PASSWORD
class Setting(object):
    EMAIL_USERNAME = "<user@Example.com>"  # 发送邮件的邮箱
    EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")  # 邮箱密码,配置环境变量:EMAIL_PASSWORD

    # Database 默认参数
    # 使用SQLALCHEMY + PYMYSQL操作数据库
    # 配置参见:https://www.osgeo.cn/sqlalchemy/core/engines.html
    DB = {
        'HOST': '192.167.6.139',
        'PORT': 3307,
        'USERNAME': 'test',
        'PASSWORD': os.getenv('DB_PASSWORD'),
        'DBNAME': 'login-register'
    }
    URI = f"mysql+pymysql://{DB['USERNAME']}:{DB['PASSWORD']}@{DB['HOST']}:{DB['PORT']}/{DB['DBNAME']}"
    SQLALCHEMY_DATABASE_URI = URI
    SQLALCHEMY_COMMIT_ON_TEARDOWN = False  # 自动提交数据处理
    SQLALCHEMY_TRACK_MODIFICATIONS = False  # 自动更跟踪数据库,性能不好
    SQLALCHEMY_POOL_SIZE = 10  # 连接数,默认5
    SQLALCHEMY_MAX_OVERFLOW = 20  # 超出连接数时,允许再新建的连接数,但是这5个人时不使用时,直接回收,默认10
    SQLALCHEMY_POOL_TIMEOUT = 30  # 等待可用连接时间,超时则报错,默认为30秒
    SQLALCHEMY_POOL_RECYCLE = 3600  # 连接生存时长(秒),超过则该连接被回收,再生存新连接,默认-1不回收连接
    SQLALCHEMY_POOL_PRE_PING = True  # 连接池的“预ping”,在每次签出时测试连接的活动性,若出现disconnect错误,该连接将立即被回收

    SQLALCHEMY_ECHO = False  # 显示原始SQL语句
    SQLALCHEMY_ECHO_POOL = False  # 连接池记录信息


class DevelopConfig(Setting):
    """开发环境"""
    # Database
    SQLALCHEMY_ECHO = True  # 显示原始SQL语句
    SQLALCHEMY_ECHO_POOL = True  # 连接池记录信息


# 环境映射关系
mapping = {
    'develop': DevelopConfig,
}

CONFIG = mapping[os.environ.get('APP_ENV', 'develop').lower()]()  # 获取指定的环境


第2步

新建 db/__init__.py中,创建数据库连接和会话

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : QtLoginRegistration 
@ File        : __init__.py.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 
"""

from sqlalchemy import create_engine
from sqlalchemy.orm import declarative_base, sessionmaker

from setting import CONFIG

# 创建连接
engine = create_engine(
    url=CONFIG.SQLALCHEMY_DATABASE_URI,
    pool_size=CONFIG.SQLALCHEMY_POOL_SIZE,
    max_overflow=CONFIG.SQLALCHEMY_MAX_OVERFLOW,
    pool_recycle=CONFIG.SQLALCHEMY_POOL_RECYCLE,
    pool_timeout=CONFIG.SQLALCHEMY_POOL_TIMEOUT,
    pool_pre_ping=CONFIG.SQLALCHEMY_POOL_PRE_PING,
    echo=CONFIG.SQLALCHEMY_ECHO,
    echo_pool=CONFIG.SQLALCHEMY_ECHO_POOL
)

# 连接会话
SessionLocal = sessionmaker(bind=engine, autocommit=False, autoflush=False)

Base = declarative_base()


# 上下文管理,管理会话
@contextmanager
def session_factory():
    session = SessionLocal()
    try:
        yield session
    except Exception:
        session.rollback()
        raise
    finally:
        session.close()


第3步

新建 db/models.py,存放数据库映射模型

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
@ Project     : QtLoginRegistration 
@ File        : models.py
@ Author      : yqbao
@ Version     : V1.0.0
@ Description : 
"""
from sqlalchemy import UniqueConstraint
from sqlalchemy import Column, Integer, String, DateTime

from db import Base


class User(Base):
    """用户表"""
    __tablename__ = 'user'  # 指定表名
    id = Column(Integer, primary_key=True, autoincrement=True, nullable=False)
    name = Column(String(255), nullable=True, comment='用户名称')
    username = Column(String(20), nullable=False, comment='用户账号')
    password = Column(String(255), nullable=False, comment='密码')
    email = Column(String(255), nullable=False, comment='邮箱')
    sex = Column(SmallInteger, nullable=True, server_default='1', comment='性别:男1,女0')
    disabled = Column(SmallInteger, nullable=False, server_default='1', comment='禁用用户:启动1,禁用0')

    createTime: str = Column(DateTime, nullable=False, comment='创建时间')
    deleted = Column(SmallInteger, nullable=False, server_default='0', comment='删除:删除0')

    UniqueConstraint(username, name='usernameUnique')  # 账号唯一
    UniqueConstraint(email, name='emailUnique')  # 邮箱唯一

    def __repr__(self):
        return '<user %r,%r>' % (self.id, self.username)


if __name__ == '__main__':
    from db import engine

    Base.metadata.drop_all(bind=engine)  # 删除所有表
    Base.metadata.create_all(bind=engine)  # 创建所有表


第4步

  • MySQL数据库中,创建名为login-register数据库
  • 执行db/modules.py,创建用户表
  • 最终效果如下
    image
  • 并插入一个测试用户,用户密码是:111111
INSERT INTO `login-register`.`user` (`id`, `name`, `username`, `password`, `email`, `sex`, `disabled`, `createTime`, `deleted`) VALUES (1, '', 'test', '$2b$12$NqJM6ypRZfg..w5uWsrS/uxz/bi6TSIpKQZBpD20dCy96Fk47p6PS', 'user@Example.com', '1', '1', '2024-02-02 13:05:57', '0');

GitHub完整代码
本文章的原文地址
GitHub主页

posted @ 2024-02-02 13:15  星尘的博客  阅读(281)  评论(0编辑  收藏  举报