Hello,
Is there a way to specify a default value for a Data Widget Mapper if a user leaves a mapped field empty? The mapper appears to ignore the db schema's default declarations. Ideally, I'd like to insert Null. Something analogous to this:
test=# INSERT INTO gear (name, addr) VALUES ('qwe', Null);My test case example has a table with a MACADDR field. There are times when a user would enter a valid macaddr and times when the macaddr field should be left blank. Note that the QSQLITE driver happily allows the field to be filled-in or not. But the QPSQL driver appears to validate the macaddr field. When empty, this causes the mapper's model to fail with an invalid input syntax error on submitAll(). eg:
ERROR: invalid input syntax for type macaddr: "" QPSQL: Unable to create query
Attached please find a simple example program, mapperTest.py, and a db schema file, test_db.sql. (Not sure how to combine the two into a single .py file.) To recreate the db from the cmd-line:
% createdb test % psql test < test_db.sql Thanks in advance! Scott
#!/usr/bin/env python #------------------------------------------------------------------------------- # imports #------------------------------------------------------------------------------- import sys, os from PyQt4 import QtCore, QtGui, QtSql MAC = "qt_mac_set_native_menubar" in dir() # table field enumeration ID, NAME, ADDR = range(3) #------------------------------------------------------------------------------- # class #------------------------------------------------------------------------------- class MapperTest(QtGui.QDialog): def __init__(self, parent=None): QtGui.QDialog.__init__(self) # init # ------------------------------------------------ self.theFrame = QtGui.QFrame() self.theFrame.setFrameStyle(QtGui.QFrame.StyledPanel|QtGui.QFrame.Sunken) # type group # ------------------------------------------------ self.typeGroup = QtGui.QGroupBox() self.nameLabel = QtGui.QLabel(self.tr("Name")) self.nameEdit = QtGui.QLineEdit() self.addrLabel = QtGui.QLabel(self.tr("MAC")) self.addrEdit = QtGui.QLineEdit() # layout self.typeLayout = QtGui.QGridLayout() self.typeLayout.addWidget(self.nameLabel, 0, 0) self.typeLayout.addWidget(self.nameEdit, 0, 1) self.typeLayout.addWidget(self.addrLabel, 1, 0) self.typeLayout.addWidget(self.addrEdit, 1, 1) self.typeGroup.setLayout(self.typeLayout) # data model # ------------------------------------------------ self.theModel = QtSql.QSqlRelationalTableModel(self) self.theModel.setTable("gear") self.theModel.setSort(NAME, QtCore.Qt.AscendingOrder) self.theModel.setEditStrategy(QtSql.QSqlTableModel.OnManualSubmit) self.theModel.setHeaderData(ID, QtCore.Qt.Horizontal, QtCore.QVariant("ID")) self.theModel.setHeaderData(NAME, QtCore.Qt.Horizontal, QtCore.QVariant("NAME")) self.theModel.setHeaderData(ADDR, QtCore.Qt.Horizontal, QtCore.QVariant("ADDR")) select = self.theModel.select() print "theModel select: ", select print self.theModel.lastError().text() # data widget mapper # ------------------------------------------------ self.mapper = QtGui.QDataWidgetMapper(self) self.mapper.setSubmitPolicy(QtGui.QDataWidgetMapper.ManualSubmit) self.mapper.setModel(self.theModel) self.mapper.setItemDelegate(QtSql.QSqlRelationalDelegate(self)) self.mapper.addMapping(self.nameEdit, NAME) self.mapper.addMapping(self.addrEdit, ADDR) self.mapper.toFirst() # buttons # ------------------------------------------------ self.newButton = QtGui.QPushButton("New") self.delButton = QtGui.QPushButton("Delete") self.commitButton = QtGui.QPushButton("Commit") # disable delete button by default self.delButton.setEnabled(False) # buttons don't get tabbing focus on non-OSX platforms if not MAC: self.newButton.setFocusPolicy(QtCore.Qt.NoFocus) self.delButton.setFocusPolicy(QtCore.Qt.NoFocus) self.commitButton.setFocusPolicy(QtCore.Qt.NoFocus) # button group layout self.buttonGroup = QtGui.QGroupBox() self.buttonLayout = QtGui.QHBoxLayout() self.buttonLayout.addStretch() self.buttonLayout.addWidget(self.newButton) self.buttonLayout.addWidget(self.delButton) self.buttonLayout.addWidget(self.commitButton) self.buttonLayout.addStretch() self.buttonGroup.setLayout(self.buttonLayout) # main layout # ------------------------------------------------ self.widgetLayout = QtGui.QVBoxLayout() self.widgetLayout.addWidget(self.typeGroup) self.widgetLayout.addWidget(self.buttonGroup) self.widgetLayout.addStretch() self.formLayout = QtGui.QHBoxLayout() self.formLayout.addLayout(self.widgetLayout) self.theFrame.setLayout(self.formLayout) self.theLayout = QtGui.QVBoxLayout() self.theLayout.addWidget(self.theFrame) self.setLayout(self.theLayout) # signals/slots # ------------------------------------------------ self.connect(self.newButton, QtCore.SIGNAL("clicked()"), self.newRecord) self.connect(self.commitButton, QtCore.SIGNAL("clicked()"), self.commit) # methods # ------------------------------------------------ def commit(self): print "commit() ..." row = self.mapper.currentIndex() submit = self.mapper.submit() print "mapper: ", submit if submit == False: print self.theModel.lastError().text() self.mapper.setCurrentIndex(row) submit = self.theModel.submitAll() print "model: ", submit if submit == False: print self.theModel.lastError().text() def newRecord(self): print "newRecord() ..." row = self.theModel.rowCount() submit = self.mapper.submit() self.theModel.insertRow(row) self.mapper.setCurrentIndex(row) self.nameEdit.setFocus() def deleteRecord(self): print "deleteRecord() ..." #------------------------------------------------------------------------------- # main #------------------------------------------------------------------------------- if __name__ == "__main__": app = QtGui.QApplication(sys.argv) # filename = os.path.join(os.path.dirname(__file__), "test.db") # create = not QtCore.QFile.exists(filename) # db = QtSql.QSqlDatabase.addDatabase("QSQLITE") # db.setDatabaseName(filename) db = QtSql.QSqlDatabase.addDatabase("QPSQL") db.setDatabaseName("test") if not db.open(): QtGui.QMessageBox.warning(None, "Foo", QtCore.QString("Database Error: %1").arg(db.lastError().text())) sys.exit(1) ok = db.open() print "db connection: ", ok form = MapperTest() form.setWindowTitle("Mapper Test") form.show() sys.exit(app.exec_())
test_db.sql
Description: Binary data
_______________________________________________ PyQt mailing list PyQt@riverbankcomputing.com http://www.riverbankcomputing.com/mailman/listinfo/pyqt