2

I'm trying to understand the advantage of using QSqlRelationalTableModel versus QSqlTableModel when dealing with tables linked through unique IDs. In the following example, the organization field is correctly displayed by name instead of by ID number. However, how would I access the corresponding "size" or "address" fields of the linked record?

from PySide.QtCore import *
from PySide.QtGui import *
from PySide.QtSql import *

db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("relational_test_01.sqlite")
db.open()
q = QSqlQuery()
q.exec_("CREATE TABLE people(id INTEGER PRIMARY KEY, first VARCHAR(50), last VARCHAR(50), organization INTEGER)")
q.exec_("INSERT INTO people VALUES(1,'John', 'Smith', 1)")
q.exec_("INSERT INTO people VALUES(2,'Bob', 'Jones', 2)")
q.exec_("CREATE TABLE organizations(id INTEGER PRIMARY KEY, name VARCHAR(50),  size INTEGER, address VARCHAR(50))")
q.exec_("INSERT INTO organizations VALUES(1,'Central Gym', 30, '400 Central Street')")
q.exec_("INSERT INTO organizations VALUES(2,'Shoe Store', 5, '200 Central Street')")

db.close()


model = QSqlRelationalTableModel()
model.setTable("people")
model.setRelation(3, QSqlRelation("organizations", "id", "name"))
model.setFilter("people.id = 1")
model.select()
count = model.rowCount()
if count == 1:
    record = model.record(0)
    org = record.value(3)
    print(org)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
davideps
  • 541
  • 3
  • 13

1 Answers1

2

There is a missing feature here, which has been reported as QTBUG-9320. Specifically, there is no obvious way to get the original foreign key value from the related table.

Fortunately, there is an undocumented work-around that avoids the issue. This works by exploiting the third argument of QSqlRelation, which is actually able to specifiy more than one column in the result.

Here is how to to get this to work in your example:

model = QSqlRelationalTableModel()
model.setTable("people")
model.setRelation(3, QSqlRelation("organizations", "id", "name, relTblAl_3.id"))
model.setFilter("people.id = 1")
model.select()
record = model.record(0)
for i in range(record.count()):
    print((i, record.value(i)))
org_model = model.relationModel(3)
org_model.setFilter('organizations.id = %s' % record.value(4))
org_model.select()
record = org_model.record(0)
print()
for i in range(record.count()):
    print((i, record.value(i)))

output:

(0, 1)
(1, 'John')
(2, 'Smith')
(3, 'Central Gym')
(4, 1)

(0, 1)
(1, 'Central Gym')
(2, 30)
(3, '400 Central Street')

The relTblAl_3.id is needed to avoid name clashes, and is documented in the notes at the end of the Detailed Description for QSqlRelationalTableModel. However, this can be avoided if you always use unique names for every column (e.g. using org_id instead of id would not then require qualification with the table name).

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thank you. Though the "relTblAl_3" functionality is documented, it feels obscure. Regardless, I'm glad it exists. You've answered every one of my PySide questions over the last few weeks. Is there a way to contact you directly in regards to a project? – davideps Oct 03 '17 at 05:56
  • @davideps. I'm glad you've found my answers helpful. At the moment, I'm afraid I cannot get involved in any other projects, as I already have other commitments. I will always look at any pyqt/pyside related questions that are posted here, though. I can't promise that I'll always be able to answer them - but I will at least comment if I think I have something useful to add. – ekhumoro Oct 03 '17 at 13:38
  • I understand. Talented people are often busy :) I'm new to both Python and Qt and am looking for general application guidance (consulting) and formal training in using PySide or, even better, PySide2. I've walked through many of the tutorials available online, but the approach seems piecemeal. Qt company does not appear to offer PySide training right now and there are no recent books on the subject. Do you have any advice? Is my only option to learn Python by itself and struggle through the C++ and older PySide manual pages for Qt? – davideps Oct 04 '17 at 06:58
  • @davideps. Although it's somewhat out of date, [Rapid GUI Programming with Python and Qt](http://www.qtrac.eu/pyqtbook.html) is probably still the best single reference available (if you want to try before you buy, it's not hard to find a pdf to download). It's written for pyqt4, but should be at least 95% compatible with pyside. It also uses [old-style signal and slot syntax](http://pyqt.sourceforge.net/Docs/PyQt4/old_style_signals_slots.html), but it's not hard to translate that into the [new-style syntax](http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html). – ekhumoro Oct 04 '17 at 13:21
  • Thank you for the recommendation. Perhaps you should write the next book on the subject. – davideps Oct 04 '17 at 13:34
  • @davideps. There is a large repository of [pyside code](https://github.com/pyside/Examples) which has ports of many of the examples from the qt docs, and the [pyqt source code packages](https://www.riverbankcomputing.com/software/pyqt/download) have an an even larger set. There is also an old [pyqt wiki](https://wiki.python.org/moin/PyQt) which still has lots of useful examples and info. – ekhumoro Oct 04 '17 at 13:35
  • @davideps. The qt docs should always be the touchstone, though. When I stated learning, I knew no c++, and there was no pyqt documentation, very little example code - and not even a wiki. A group of people on the pyqt mailing list decided to rectify that, and started an effort to port all the examples from the qt docs. So I joined that effort, and that is how I cut my teeth learning pyqt (and also a little c++). Once you get your head around translating c++ code to pyqt, everything becomes much easier - because there is no better tutorial than reading the qt docs. – ekhumoro Oct 04 '17 at 13:46
  • If Qt Company is now officially supporting PySide2 will that become the standard and documentation follow? – davideps Oct 04 '17 at 13:54
  • @davideps. TBH, I don't really know. I started just after PyQt3 was first released, and PySide arrived much later on - so I know much more about PyQt. I haven't yet tried out PySide2, and don't know much about it's development history. The [mailing list](http://lists.qt-project.org/pipermail/pyside/) has very low traffic. It will probably be a long time before it gains more traction than PyQt, which has had a big head start. At the moment, the only adavantage PySide has is the licensing. Maybe PySide2 will offer more - but development of PyQt isn't going to stand still... – ekhumoro Oct 04 '17 at 14:10