当前位置: 首页 > web >正文

Qt小组件 - 7 SQL Thread Qt访问数据库ORM

简介

网上关于Qt访问数据库的资料大多使用QSqlDatabase模块。虽然这在C++中尚可接受,但在Python中使用就显得过于繁琐了——不仅要手动编写SQL语句,还与Python追求简洁的理念背道而驰。

在这里写一个基于sqlalchemy的示例,也可以使用其他的ORM

sql_thread.py

# coding: utf-8
from collections import deque
from typing import Callablefrom PySide6.QtCore import QObject, Signal, QThread
from sqlalchemy.orm import Sessionclass SqlRequest:""" Sql request """def __init__(self, func: Callable, slot: Callable = None, params: dict = None):self.func = funcself.slot = slotself.params = params or {}class SqlResponse:""" Sql的反应 """def __init__(self, data: object, slot: Callable = None):self.slot = slotself.data = dataclass SqlSignalBus(QObject):""" Sql信号总线 """fetchDataSig = Signal(SqlRequest)dataFetched = Signal(SqlResponse)sqlSignalBus = SqlSignalBus()def sqlRequest(func: Callable, slot=None, **params):""" 从数据库查询 SQL 数据 """request = SqlRequest(func, slot, params)sqlSignalBus.fetchDataSig.emit(request)class DatabaseThread(QThread):def __init__(self, parent=None):super().__init__(parent=parent)self.server = Noneself.tasks = deque()sqlSignalBus.fetchDataSig.connect(self.onFetchData)def run(self):func, args, kwargs = self.serverserver: Session = func(*args, **kwargs)while self.tasks:request: SqlRequest = self.tasks.popleft()result = request.func(**request.params, server=server)sqlSignalBus.dataFetched.emit(SqlResponse(result, request.slot))server.close()def setServer(self, func: Callable, *args, **kwargs):self.server = (func, args, kwargs)def onFetchData(self, request: SqlRequest):self.tasks.append(request)if not self.isRunning():self.start()

db.py

# coding: utf-8
from random import randint, choicefrom sqlalchemy import Column, Integer, String
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Sessionengine = create_engine('sqlite:///test.db')
Base = declarative_base()def create_session():return sessionmaker(bind=engine)()def init_create_table() -> None:Base.metadata.create_all(bind=engine, checkfirst=True)class User(Base):# 表的名字:__tablename__ = 'user'# 表的结构:id = Column(Integer, autoincrement=True, primary_key=True, comment='用户ID')name = Column(String(20))age = Column(Integer)phone = Column(String(20))email = Column(String(50))sex = Column(String(10))def __repr__(self):return f"User(id={self.id}, name={self.name}, age={self.age}, phone={self.phone}, email={self.email}, sex={self.sex})"def add_user(server: Session):server.add(User(name=f'Tom-{randint(1, 100)}', age=randint(1, 100), phone=str(randint(10000000, 99999999)),email='tom@123.com',sex=choice(['male', 'female'])))server.commit()def select_user(server: Session):users = server.query(User).all()return users

demo.py

# coding: utf-8
import sysfrom PySide6.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayoutfrom db import create_session, User, add_user, select_user, init_create_table
from sql_thread import sqlSignalBus, SqlResponse, DatabaseThread, sqlRequestclass MainWindow(QWidget):def __init__(self):super().__init__()self.setWindowTitle("Sql Thread Example")self.horizontalLayout = QHBoxLayout(self)self.addUserButton = QPushButton("Add User", self)self.selectUserButton = QPushButton("Select User", self)self.horizontalLayout.addWidget(self.addUserButton)self.horizontalLayout.addWidget(self.selectUserButton)self.resize(400, 300)self.databaseThread = DatabaseThread(self)self.databaseThread.setServer(create_session)sqlSignalBus.dataFetched.connect(self.onDataFetched)self.addUserButton.clicked.connect(lambda: sqlRequest(add_user))self.selectUserButton.clicked.connect(lambda: sqlRequest(select_user, self.onSelectUser))def onSelectUser(self, users: list[User]):print(users)def onDataFetched(self, response: SqlResponse):if response.slot:response.slot(response.data)if __name__ == '__main__':app = QApplication(sys.argv)init_create_table()mainWindow = MainWindow()mainWindow.show()sys.exit(app.exec())

在这里插入图片描述

http://www.xdnf.cn/news/15627.html

相关文章:

  • Uniapp中双弹窗为什么无法显示?
  • 玩转Docker | 使用Docker部署bender个人导航页工具
  • 利用Java自定义格式,循环导出数据、图片到excel
  • 【论文阅读 | CVPR 2023 |CDDFuse:基于相关性驱动的双分支特征分解的多模态图像融合】
  • lua(xlua)基础知识点记录
  • 【前端】在Vue3中绘制多系列柱状图与曲线图
  • 量子比特耦合与系统集成:量子计算硬件的核心突破
  • 入门华为数通,HCIA/HCIP/HCIE该怎么选?
  • 2025年自动化工程、物联网与计算机应用国际会议(AEITCA 2025)
  • Java基础:分支/循环/数组
  • PLC-BMS电力载波通信技术深度解析:智能电网与储能系统的融合创新
  • 【WRFDA数据第一期】WRFDA Free Input 数据网页
  • Spring Boot 整合 Nacos 实战教程:服务注册发现与配置中心详解
  • 【后端】.NET Core API框架搭建(6) --配置使用MongoDB
  • 微软AutoGen:多智能体协作的工业级解决方案
  • PyCharm高效入门
  • NodeJS Express 静态文件、中间件、路由案例
  • 手撕Spring底层系列之:IOC、AOP
  • java操作Excel两种方式EasyExcel 和POI
  • 跟着Carl学算法--回溯【2】
  • React Hooks 数据请求库——SWR使用详解
  • Spring AI 系列之十四 - RAG-ETL之一
  • Vue3+Ts实现父子组件间传值的两种方式
  • Unity Android Logcat插件 输出日志中文乱码解决
  • 小白成长之路-Elasticsearch 7.0 配置
  • BNN 技术详解:当神经网络只剩下 +1 和 -1
  • 基于redis的分布式锁 lua脚本解决原子性
  • 免杀学习篇(1)—— 工具使用
  • 网页源码保护助手 海洋网页在线加密:HTML 源码防复制篡改,密文安全如铜墙铁壁
  • 基于华为欧拉系统安装FileGator文件管理器