[PyQt] QSqlTableModel doesn't know submitted records any more with PostgreSQL database

Sibylle Koczian nulla.epistola at web.de
Sun Feb 15 11:44:25 GMT 2015


No answer up to now, why? Is this mailing list the wrong place? This 
might be a Qt problem, should I try the Qt forum?

Or did I leave out important information? If yes, what?

I'll put the code at the end of this mail in case there were problems 
with the attachment.

Am 11.02.2015 um 20:26 schrieb Sibylle Koczian:
> Hello,
>
> when I insert data into a PostgreSQL database table using a
> QSqlTableModel they are written to the database, but I can't see them in
> the appliction after submitting. This happens with tables whose primary
> key has type SERIAL, it doesn't happen if the primary key is inserted by
> hand.
>
> This doesn't happen with SQLite databases and it doesn't happen if I use
> PyQt4.
>
> I've attached a small example which uses the following tables:
>
> CREATE TABLE states
> (
>    cc character(2) NOT NULL,
>    name character varying(50) NOT NULL,
>    CONSTRAINT states_pkey PRIMARY KEY (cc)
> )
>
> CREATE TABLE towns
> (
>    id serial NOT NULL,
>    name character varying(50) NOT NULL,
>    cc character(2) NOT NULL,
>    CONSTRAINT towns_pkey PRIMARY KEY (id),
>    CONSTRAINT towns_cc_fkey FOREIGN KEY (cc)
>        REFERENCES states (cc) MATCH SIMPLE
>        ON UPDATE NO ACTION ON DELETE NO ACTION,
>    CONSTRAINT towns_name_cc_key UNIQUE (name, cc)
> )
>
> Running the application on Windows 7, using Python 3.4.2, PyQt 5.4 gives
> the following output:
>
> Result using SQLite (5 states, 7 towns before starting):
>
> d:\home\...\pyqt5_sql>statoids_model_cons.py lite
> New state, example: HE Hessen: NI Niedersachsen
> DEBUG:__main__:Before submit, new record in row 6: Niedersachsen (NI)
> DEBUG:__main__:After submit, new record in row 6: Niedersachsen (NI)
> New town in NI: Düsseldorf
> DEBUG:__main__:Before submit, new record in row 8: Düsseldorf in NI, PK 0
> DEBUG:__main__:After submit, new record in row 8: Düsseldorf in NI, PK 9
> BW: Baden-Württemberg
> ...
> NI: Niedersachsen
> 1: Frankfurt in HE
> ...
> 9: Düsseldorf in NI
> DEBUG:__main__:Model data created and shown
>
> Everything as expected.
>
> Result using PostgreSQL 9.4 (1 state, 1 town before starting):
>
> d:\home\...\pyqt5_sql>statoids_model_cons.py pg
> New state, example: HE Hessen: NI Niedersachsen
> DEBUG:__main__:Before submit, new record in row 1: Niedersachsen (NI)
> DEBUG:__main__:After submit, new record in row 1: Niedersachsen (NI)
> New town in NI: Düsseldorf
> DEBUG:__main__:Before submit, new record in row 1: Düsseldorf in NI, PK 0
> DEBUG:__main__:After submit, new record in row 1: None in None, PK None ***
> HE: Hessen
> NI: Niedersachsen
> 1: Frankfurt in HE
> None: None in None ***
> DEBUG:__main__:Model data created and shown
>
> Lines with *** show the problem, I think. The new record gets into the
> database, but it can be important to see it in the application.
>
> What can I do? Can this be a bug in QPSQL?
>

Here is the code:

#!/usr/bin/env python3
# statoids_model_cons.py
# QTableView and QDataWidgetMapper
# Model for all parts of the application, using PostgreSQL

import os
import sys
import logging
from PyQt5 import QtCore
from PyQt5 import QtSql

modlog = logging.getLogger(__name__)

def createSQLiteConnection():
     filename = os.path.join(os.path.dirname(__file__), "statoids.db")
     db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
     db.setDatabaseName(filename)
     ok = db.open()
     msg = "Database Error: {}".format(db.lastError().text())
     if ok:
         query = QtSql.QSqlQuery()
         okp = query.exec_("""PRAGMA foreign_keys = ON""")
         if not okp:
             modlog.error("Pragma: {}".format(db.lastError().text()))
     else:
         modlog.error(msg)
     return (ok, msg)

def createPGConnection():
     db = QtSql.QSqlDatabase.addDatabase("QPSQL")
     db.setDatabaseName("...")
     db.setHostName("localhost")
     db.setUserName("...")
     db.setPassword("...")
     ok = db.open()
     msg = "Database Error: {}".format(db.lastError().text())
     return (ok, msg)


class StatesModel(QtSql.QSqlTableModel):

     def __init__(self, parent=None):
         super().__init__(parent)
         self.setTable('states')
         self.setEditStrategy(QtSql.QSqlTableModel.OnRowChange)
         #self.setSort(1, QtCore.Qt.AscendingOrder)
         for (col, header) in enumerate(["CC", "Name"]):
             self.setHeaderData(col, QtCore.Qt.Horizontal, header)
         self.select()

     def addNew(self, newcc, newstate):
         zz = self.rowCount()
         self.insertRow(zz)
         self.setData(self.index(zz, 0), newcc)
         self.setData(self.index(zz, 1), newstate)
         modlog.debug("Before submit, new record in row %d: %s (%s)",
                      zz, self.data(self.index(zz, 1)),
                      self.data(self.index(zz, 0)))
         self.submit()
         modlog.debug("After submit, new record in row %d: %s (%s)",
                      zz, self.data(self.index(zz, 1)),
                      self.data(self.index(zz, 0)))

     def showData(self):
         for row in range(self.rowCount()):
             rec = self.record(row)
             print("{0}: {1}".format(rec.value(0), rec.value(1)))


class TownsModel(QtSql.QSqlTableModel):

     def __init__(self, parent=None):
         super().__init__(parent)
         self.setTable('towns')
         self.setEditStrategy(QtSql.QSqlTableModel.OnRowChange)
         #self.setSort(1, QtCore.Qt.AscendingOrder)
         for (col, header) in enumerate(["ID", "Name", "CC"]):
             self.setHeaderData(col, QtCore.Qt.Horizontal, header)
         self.select()

     def addNew(self, newcc, newtown):
         zz = self.rowCount()
         self.insertRow(zz)
         self.setData(self.index(zz, 1), newtown)
         self.setData(self.index(zz, 2), newcc)
         modlog.debug("Before submit, new record in row %d: %s in %s, PK 
%s",
                      zz, self.data(self.index(zz, 1)),
                      self.data(self.index(zz, 2)), 
self.data(self.index(zz, 0)))
         self.submit()
         modlog.debug("After submit, new record in row %d: %s in %s, PK 
%s",
                      zz, self.data(self.index(zz, 1)),
                      self.data(self.index(zz, 2)), 
self.data(self.index(zz, 0)))

     def showData(self):
         for row in range(self.rowCount()):
             rec = self.record(row)
             print("{0}: {1} in {2}".format(rec.value(0), rec.value(1),
                                            rec.value(2)))


def addData(statesmodel, townsmodel):
     newdata = input("New state, example: HE Hessen: ")
     (newcc, newstate) = newdata.split()
     statesmodel.addNew(newcc, newstate)
     newtown = input("New town in {}: ".format(newcc))
     townsmodel.addNew(newcc, newtown)
     statesmodel.showData()
     townsmodel.showData()

def choose_dbms(args):
     dbs_ok = False
     if args:
         dbs = args.pop()
         dbs_ok = dbs in ("pg", "lite")
     if not dbs_ok:
         dbs = input("Which DBMS (pg - PostgreSQL, lite - SQLite)? ")
     return (dbs, args)

if __name__ == "__main__":
     logging.basicConfig(level=logging.DEBUG)
     (dbs, args) = choose_dbms(sys.argv[1:])
     app = QtCore.QCoreApplication(args)
     (ok, msg) = (createPGConnection() if dbs == "pg"
                  else createSQLiteConnection())
     if ok:
         addData(StatesModel(), TownsModel())
         modlog.debug("Model data created and shown")
     else:
         modlog.error(msg)




More information about the PyQt mailing list