[英]How can I add records to my SQLite database, using PySide2, that have NULL values?
我有一個 PySide2 GUI,可以在我的 SQLite3 數據庫中添加、更新和刪除記錄。 我使用 QTableView 查看數據,使用 QDataWidgetMapper 編輯數據。
我的問題是,當我向數據庫中添加一條在任何字段中都有空白值的記錄時,它不會在數據庫中注冊為 NULL 值,只有一個空白字符串 ("")。 我認為我沒有以正確的方式實施委托。 我應該在列上還是在 QDataWidgetMapper 上設置委托?
import sys
import os
from PySide2 import QtCore, QtGui, QtWidgets, QtSql
import PySide2.QtUiTools as QtUiTools
import sqlite3
class NullDelegate(QtWidgets.QStyledItemDelegate):
def __init__(self, parent=None):
super(NullDelegate, self).__init__(parent)
def createEditor(self, parent, options, index):
editor = QtWidgets.QLineEdit(parent)
return editor
def setEditorData(self, editor, index):
if index.siblingAtColumn(1).data() == "": # This is for testing purposes
print(index.siblingAtColumn(2).data())
if index.data():
editor.setText(str(index.data()))
editor.selectAll() # This is for testing purposes
def setModelData(self, editor, model, index):
value = editor.text()
if value == "":
print("null value")
model.setData(index, None, QtCore.Qt.EditRole)
else:
model.setData(index, value, QtCore.Qt.EditRole)
class Main(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
# load ui file
loader = QtUiTools.QUiLoader()
# The UI file must be a widget, NOT MainWindow, to load into a QMainWindow object
# otherwise you will have to use .show() to open in separate window
path = os.path.join(os.path.dirname(__file__), "main.ui")
self.main = loader.load(path, self)
# create SQLite Database and Table
db = QtSql.QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("customers_demo.db")
if db.open():
print('connection open')
query = QtSql.QSqlQuery(db=db)
query.prepare("CREATE TABLE IF NOT EXISTS Customers_demo (ID INT PRIMARY KEY, FEIN varchar(255), CustomerName varchar(255), Address varchar(255), City varchar(255), State varchar(255), Zip INT) ")
query.exec_()
# Set up QSqlTableModel
self.model = QtSql.QSqlTableModel(self)
self.model.setTable("customers_demo")
self.model.select()
# Set up QDataWidgetMapper
self.mapper = QtWidgets.QDataWidgetMapper()
self.mapper.setModel(self.model)
# Set up the delegate for null values
null_delegate = NullDelegate(self.main.tableView)
self.mapper.setItemDelegate(null_delegate)
# Configure QDataWidgetMapper
self.mapper.addMapping(self.main.id_lineEdit, 0)
self.mapper.addMapping(self.main.fein_lineEdit, 1)
self.mapper.addMapping(self.main.customer_lineEdit, 2)
self.mapper.addMapping(self.main.address_lineEdit, 3)
self.mapper.addMapping(self.main.city_lineEdit, 4)
self.mapper.addMapping(self.main.state_lineEdit, 5)
self.mapper.addMapping(self.main.zip_lineEdit, 6)
self.mapper.setSubmitPolicy(self.mapper.ManualSubmit)
# Set up QTableView
self.main.tableView.setModel(self.model)
# Set up the delegate for null values
# null_delegate = NullDelegate(self.main.tableView)
# self.main.tableView.setItemDelegateForColumn(1, null_delegate)
self.main.tableView.resizeColumnsToContents()
# QTableView properties
self.main.tableView.setSortingEnabled(True) # sort by clicking title
self.main.tableView.resizeColumnToContents(2) # "Customer Name" column
self.main.tableView.setSelectionBehavior(
QtWidgets.QAbstractItemView.SelectRows)
# add background color to every other row
self.main.tableView.setAlternatingRowColors(True)
# make table uneditable
self.main.tableView.setEditTriggers(
QtWidgets.QTableView.NoEditTriggers)
self.mapper.setCurrentIndex(0)
print(self.mapper.currentIndex())
self.RECORD_NUMBER()
self.handle_buttons()
def handle_buttons(self):
self.main.update_btn.clicked.connect(self.UPDATE)
self.main.delete_btn.clicked.connect(self.DELETE)
self.main.new_btn.clicked.connect(self.NEW)
self.main.first_btn.clicked.connect(self.mapper.toFirst)
self.main.first_btn.clicked.connect(self.RECORD_NUMBER)
self.main.previous_btn.clicked.connect(self.mapper.toPrevious)
self.main.previous_btn.clicked.connect(self.RECORD_NUMBER)
self.main.next_btn.clicked.connect(self.mapper.toNext)
self.main.next_btn.clicked.connect(self.RECORD_NUMBER)
self.main.last_btn.clicked.connect(self.mapper.toLast)
self.main.last_btn.clicked.connect(self.RECORD_NUMBER)
self.main.tableView.clicked.connect(self.SELECT_ROW)
def SELECT_ROW(self, item):
# Set text to the selected customer info
self.main.id_lineEdit.setText(
str(item.siblingAtColumn(0).data())) # convert int to str
self.main.customer_lineEdit.setText(item.siblingAtColumn(2).data())
self.main.fein_lineEdit.setText(item.siblingAtColumn(1).data())
self.main.address_lineEdit.setText(item.siblingAtColumn(3).data())
self.main.city_lineEdit.setText(item.siblingAtColumn(4).data())
self.main.state_lineEdit.setText(item.siblingAtColumn(5).data())
self.main.zip_lineEdit.setText(
str(item.siblingAtColumn(6).data())) # convert int to str
self.mapper.setCurrentIndex(item.row())
self.RECORD_NUMBER()
def UPDATE(self):
loader = QtUiTools.QUiLoader()
path = os.path.join(os.path.dirname(__file__), "dialog.ui")
dialog = loader.load(path)
currentIndex = self.mapper.currentIndex()
print("Mapper", currentIndex)
self.main.tableView.selectRow(currentIndex)
customer = self.main.tableView.currentIndex().siblingAtColumn(2).data()
print(customer)
text = f"Are you sure you want to UPDATE {customer} info?"
dialog.label.setText(text)
dialog.buttonBox.accepted.connect(dialog.accept)
dialog.buttonBox.rejected.connect(dialog.reject)
dialog.show()
if dialog.exec_():
print("update")
te = self.mapper.submit()
print(te)
print(self.mapper.model())
self.model.select()
else:
pass
def DELETE(self):
loader = QtUiTools.QUiLoader()
path = os.path.join(os.path.dirname(__file__), "dialog.ui")
dialog = loader.load(path)
currentIndex = self.mapper.currentIndex()
print("Mapper", currentIndex)
self.main.tableView.selectRow(currentIndex)
customer = self.main.tableView.currentIndex().siblingAtColumn(2).data()
print(customer)
text = f"Are you sure you want to DELETE {customer} info?"
dialog.label.setText(text)
dialog.buttonBox.accepted.connect(dialog.accept)
dialog.buttonBox.rejected.connect(dialog.reject)
dialog.show()
if dialog.exec_():
print("yes")
self.model.removeRow(currentIndex)
self.model.select()
else:
pass
self.mapper.setCurrentIndex(0)
print(self.mapper.currentIndex())
self.RECORD_NUMBER()
def NEW(self):
loader = QtUiTools.QUiLoader()
path = os.path.join(os.path.dirname(__file__), "dialog.ui")
dialog = loader.load(path)
customer = self.main.customer_lineEdit.text()
text = f"Are you sure you want to ADD {customer} info?"
dialog.label.setText(text)
dialog.buttonBox.accepted.connect(dialog.accept)
dialog.buttonBox.rejected.connect(dialog.reject)
dialog.show()
if dialog.exec_():
row = self.model.rowCount()
record = self.model.record()
# record.setGenerated('id', False)
record.setValue('ID', self.main.id_lineEdit.text())
record.setValue('FEIN', str(self.main.fein_lineEdit.text()))
record.setValue("CustomerName",
self.main.customer_lineEdit.text())
record.setValue('Address', self.main.address_lineEdit.text())
record.setValue('City', self.main.city_lineEdit.text())
record.setValue('State', self.main.state_lineEdit.text())
record.setValue('Zip', self.main.zip_lineEdit.text())
self.model.insertRecord(row, record)
self.model.select()
else:
pass
self.mapper.setCurrentIndex(0)
print(self.mapper.currentIndex())
self.RECORD_NUMBER()
def RECORD_NUMBER(self):
currentIndex = self.mapper.currentIndex()
print(currentIndex)
rows = self.model.rowCount()
self.main.record_label.setText(
f"Customer {currentIndex+1} of {rows} customers")
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
widget = Main()
widget.show()
app.exec_()
我也在使用 Python 3.7.4
問題不在於委托,而在於添加行的代碼,因為您直接傳遞 QLineEdits 的文本而不實現空值的邏輯。
def NEW(self):
loader = QtUiTools.QUiLoader()
path = os.path.join(os.path.dirname(__file__), "dialog.ui")
dialog = loader.load(path)
customer = self.main.customer_lineEdit.text()
text = f"Are you sure you want to ADD {customer} info?"
dialog.label.setText(text)
dialog.buttonBox.accepted.connect(dialog.accept)
dialog.buttonBox.rejected.connect(dialog.reject)
if dialog.exec_():
mapping = {
"ID": self.main.id_lineEdit,
"FEIN": self.main.fein_lineEdit,
"CustomerName": self.main.customer_lineEdit,
"Address": self.main.address_lineEdit,
"City": self.main.city_lineEdit,
"State": self.main.state_lineEdit,
"Zip": self.main.zip_lineEdit,
}
record = self.model.record()
for fieldname, lineedit in mapping.items():
text = lineedit.text()
record.setValue(fieldname, text if text else None)
row = self.model.rowCount()
self.model.insertRecord(row, record)
self.model.select()
self.mapper.setCurrentIndex(0)
print(self.mapper.currentIndex())
self.RECORD_NUMBER()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.