You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PyQt5.QtSql显示SQLite关联表数据?

嘿,我之前也折腾过QSqlRelationalTableModel的关联查询,刚开始确实摸不着头脑,尤其是JoinMode的用法,给你分享一下我踩坑后总结的实现方法,亲测有效!

核心思路

QSqlRelationalTableModel本身就支持关联表的查询和数据展示,关键是要正确设置关联关系和连接模式,如果需要显示关联表的额外字段,还要手动指定查询列。

分步实现 + 代码示例

假设我们有两个关联表:

  • customers:存储客户信息(id, name, email)
  • orders:存储订单信息(id, customer_id, order_date, total),其中customer_id是关联customers.id的外键

1. 初始化数据库与测试数据

先搞定数据库连接和测试数据,确保关联关系有效:

import sys
from PyQt5.QtWidgets import QApplication, QTableView
from PyQt5.QtSql import (QSqlDatabase, QSqlRelationalTableModel, 
                         QSqlRelation)
from PyQt5.QtCore import Qt

# 初始化SQLite数据库
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("test.db")
if not db.open():
    print("数据库打开失败!")
    sys.exit(1)

# 开启外键约束(SQLite默认关闭)
db.exec_("PRAGMA foreign_keys = ON")

# 创建测试表
db.exec_("""
CREATE TABLE IF NOT EXISTS customers (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    email TEXT NOT NULL UNIQUE
)
""")
db.exec_("""
CREATE TABLE IF NOT EXISTS orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    customer_id INTEGER NOT NULL,
    order_date TEXT NOT NULL,
    total REAL NOT NULL,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
)
""")

# 插入测试数据
db.exec_("INSERT INTO customers (name, email) VALUES ('Alice', 'alice@example.com')")
db.exec_("INSERT INTO customers (name, email) VALUES ('Bob', 'bob@example.com')")
db.exec_("INSERT INTO orders (customer_id, order_date, total) VALUES (1, '2024-05-01', 99.99)")
db.exec_("INSERT INTO orders (customer_id, order_date, total) VALUES (2, '2024-05-02', 149.99)")

2. 配置QSqlRelationalTableModel

这一步是关键,我们要设置关联关系、连接模式,并指定要展示的字段:

app = QApplication(sys.argv)
view = QTableView()

# 初始化关联表模型
model = QSqlRelationalTableModel(db=db)
model.setTable("orders")  # 设置主表为orders

# 1. 设置外键关联:把orders表的customer_id列(索引1,从0开始)映射到customers表的name字段
# 参数:主表列索引、关联表名、关联表主键、要显示的关联表字段
model.setRelation(1, QSqlRelation("customers", "id", "name"))

# 2. 设置连接模式(JoinMode)
# 可选两种模式:
# - InnerJoin:只显示主表中存在对应关联数据的行(比如没有客户的订单会被过滤)
# - LeftJoin:显示主表所有行,关联表无匹配数据时显示空值
model.setJoinMode(QSqlRelationalTableModel.InnerJoin)

# 3. 指定要查询的字段(如果需要显示关联表的额外字段,比如客户邮箱)
# 注意要加上表名前缀,避免字段名冲突
model.setSelect("orders.id, orders.order_date, customers.name, customers.email, orders.total")

# 设置表头显示文本
model.setHeaderData(0, Qt.Horizontal, "订单ID")
model.setHeaderData(1, Qt.Horizontal, "订单日期")
model.setHeaderData(2, Qt.Horizontal, "客户姓名")
model.setHeaderData(3, Qt.Horizontal, "客户邮箱")
model.setHeaderData(4, Qt.Horizontal, "订单总额")

# 加载数据
model.select()

# 关联模型到表格视图
view.setModel(model)
view.resizeColumnsToContents()  # 自动调整列宽
view.show()

sys.exit(app.exec_())
关键注意点
  • 外键约束必须开启:SQLite默认关闭外键约束,一定要执行PRAGMA foreign_keys = ON,否则关联查询可能出问题,删除关联数据时也不会触发约束。
  • 列索引别搞错:setRelation()的第一个参数是主表的列索引,从0开始计数,比如orders表的customer_id是第二列(索引1)。
  • 编辑功能自动生效:QSqlRelationalTableModel支持编辑,当你修改客户姓名列时,模型会自动把对应的customer_id更新到orders表,不用手动写SQL。
  • JoinMode的选择:如果你的主表可能存在没有关联数据的行(比如未分配客户的订单),就用LeftJoin;如果只需要显示有完整关联数据的行,用InnerJoin。

内容的提问来源于stack exchange,提问作者CodingCat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:41:21