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

PyQt6:QSqlRelationalDelegate切换国家时自动选中首个关联城市

实现思路与代码修改

完全可以实现这个需求,核心是监听国家列的变更事件,当用户选择国家后,自动获取该国家下的首个城市ID并更新到城市列,同时确保城市下拉框打开时默认选中这个城市。

步骤1:修复现有SQL注入风险(可选但重要)

你当前代码里直接拼接SQL字符串存在注入风险,建议改用参数绑定:

q = QSqlQuery()
q.prepare("SELECT id FROM country WHERE name = :name LIMIT 1")
q.bindValue(":name", country_name)
q.exec_()

步骤2:监听国家列的变更,自动更新城市列

重写commitData方法,在用户确认国家选择后,立即更新对应行的城市值:

def commitData(self, editor):
    # 先调用父类方法提交数据
    super(MyQSqlRelationalDelegate, self).commitData(editor)
    
    # 获取当前编辑的索引
    index = self.parent().currentIndex()
    if not index.isValid():
        return
    
    # 判断是否是国家列(假设国家列是索引2)
    if index.column() == 2:
        model = index.model()
        row = index.row()
        # 获取选中的国家名称
        country_name = model.data(index)
        if not country_name:
            # 清空城市列
            model.setData(model.index(row, 3), "")
            return
        
        # 查询该国家的首个城市ID
        q = QSqlQuery()
        q.prepare("""
            SELECT city.id 
            FROM city 
            JOIN country ON city.country_id = country.id 
            WHERE country.name = :name 
            ORDER BY city.name 
            LIMIT 1
        """)
        q.bindValue(":name", country_name)
        q.exec_()
        
        if q.next():
            city_id = q.value(0)
            # 更新城市列的数值为首个城市ID
            model.setData(model.index(row, 3), city_id)

步骤3:确保城市下拉框默认选中首个城市

在现有setEditorData方法的过滤逻辑后,添加选中第一个选项的代码:

def setEditorData(self, editor, index):
    model = index.model()
    childModel = (model.relationModel(index.column()) if model is not None else None)
    if index.column() == 3 and childModel is not None: # City
        country_name = model.index(index.row(),2).data()
        if country_name is None or country_name == '':
            childModel.setFilter('')
        else:
            q = QSqlQuery()
            q.prepare("SELECT id FROM country where name=:name limit 1")
            q.bindValue(":name", country_name)
            q.exec_()
            country_id = None
            while q.next():
                country_id = q.value(0)
            if country_id is not None:
                childModel.setFilter('country_id=' + str(country_id))
        
        # 过滤后选中第一个选项
        if childModel.rowCount() > 0:
            editor.setCurrentIndex(0)
    
    super(MyQSqlRelationalDelegate, self).setEditorData(editor, index)

补充说明

  • 若使用QTableView,需确保视图设置了合适的编辑触发方式(比如setEditTriggers(QTableView.DoubleClicked))。
  • 若希望国家选择后实时更新城市(无需等待编辑提交),可监听编辑器的currentIndexChanged信号触发更新,但要注意避免循环触发问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 10:11:10