从SQLite数据库检索日期(INTEGER)并将其插入QDateEdit字段

时间:2020-09-04 10:30:07

标签: python pyqt pyqt5

我有一个简单的测试表单,其中包含2个字段:姓名,出生日期。它们都从基础SQLite数据库获取值。数据库中的生日日期字段的类型为INTEGER(UNIX时间)。我可以在表格上获得该名称,但不能获得生日(我改为1/1/2000)。我怀疑我的问题与从INTEGER到QDate的类型转换有关,但我不知道如何解决它。

下面是此简化表单版本的代码。我已经包括了重新创建问题的最低要求。如果将此代码另存为.py文件并在目录中运行,它将在该目录中创建数据库并显示表单。我正在使用“视图/模型”方法,如果可以在现有代码中使用任何答案,则将特别感谢。

非常感谢

import sys
import os.path
import sqlite3
from PyQt5 import QtWidgets as qtw
from PyQt5 import QtGui as qtg
from PyQt5 import QtCore as qtc
from PyQt5 import QtSql as qts


DIR_PATH = os.path.dirname(os.path.abspath(__file__))
DB_NAME = 'test.db'
target_db = os.path.join(DIR_PATH, DB_NAME)


 # create database 'test.db', add schema, then close it
cnn = sqlite3.connect(target_db)
c = cnn.cursor()
c.executescript("""
                            
                    DROP TABLE IF EXISTS clients;
                    CREATE TABLE clients
                    (
                        id INTEGER PRIMARY KEY,
                        name STRING,
                        birthdate INTEGER
                    );

                    INSERT INTO clients VALUES (1, 'Error Flynn', '12/30/1980');
                            
                """)
cnn.commit()
cnn.close()


class Model(qtc.QObject):

    connection_error = qtc.pyqtSignal(str)
    
    def start_db(self):

        connection_error = ''
        # create a db connection:
        self.db = qts.QSqlDatabase.addDatabase('QSQLITE')
        self.db.setDatabaseName(target_db)
        # test the connection for errors:    
        if not self.db.open():
            connection_error = f'{self.db.lastError().text()}'
            sys.exit(1)

        if connection_error:
            self.error.emit(connection_error)


    def create_model(self):

        self.clients_model = qts.QSqlRelationalTableModel()
        self.clients_model.setTable('clients')

        # query once the model to populate it
        self.clients_model.select()

        return self.clients_model


# create the Clients Form
class View(qtw.QWidget):

    error = qtc.pyqtSignal(str)
    
    def __init__(self, a_clients_model):

        super().__init__()
        self.setLayout(qtw.QFormLayout())
        
        # The 2 Client Fields
        
        self.client_name = qtw.QLineEdit()
        self.layout().addRow('Name: ', self.client_name)

        self.client_bdate = qtw.QDateEdit()
        self.layout().addRow('Birthdate: ', self.client_bdate)
        self.client_bdate.setCalendarPopup(True)
    

        # create a mapper and point it to the clients_model 
        self.this_clients_model = a_clients_model
        self.mapper = qtw.QDataWidgetMapper(self)
        self.mapper.setModel(self.this_clients_model)
        self.mapper.setItemDelegate(
            qts.QSqlRelationalDelegate(self))

        # map the Client Name field  
        self.mapper.addMapping(
            self.client_name,
            self.this_clients_model.fieldIndex('name')
        )

        # map the Client Birthdate field  
        self.mapper.addMapping(
            self.client_bdate,
            self.this_clients_model.fieldIndex('birthdate')
            # client_birthdate is declared INTEGER in the SQLite database,
            # to be converted to a QDateEdit object before it can be used!
        )

        # this will show the first record in the tbl_clients
        self.mapper.setCurrentIndex(0)
       
        self.show()


    # display error message originating in Model class
    def show_connection_error(self, error):
        qtw.QMessageBox.critical(
            None,
            'DB Connection Error',
            'Could not open database file: ' 
            f'{error}')
        sys.exit(1)


class MainWindow(qtw.QMainWindow):

    def __init__(self):
        """MainWindow constructor.
        """
        super().__init__()
        # Main UI code goes here

        self.stack = qtw.QStackedWidget()
        self.setCentralWidget(self.stack)

        self.model = Model()
        self.model.start_db()
               
        self.view = View(self.model.create_model())
        self.stack.addWidget(self.view)
        
        self.model.connection_error.connect(self.view.show_connection_error)

        # End main UI code
        self.show()


if __name__ == '__main__':
    app = qtw.QApplication(sys.argv)
    # it's required to save a reference to MainWindow.
    # if it goes out of scope, it will be destroyed.
    mw = MainWindow()
    sys.exit(app.exec())

1 个答案:

答案 0 :(得分:1)

问题是字符串“ 12/30/1980”和默认的QDate之间没有转换。在这种情况下,解决方案是使用委托进行该转换。另一方面,我认为没有必要使用QSqlRelationalDelegate作为委托。

class Delegate(qtw.QItemDelegate):
    def setEditorData(self, editor, index):
        if isinstance(editor, qtw.QDateEdit):
            dt = qtc.QDate.fromString(index.data(), "MM/dd/yyyy")
            editor.setDate(dt)
        else:
            super().setEditorData(editor, index)

    def setModelData(self, editor, model, index):
        if isinstance(editor, qtw.QDateEdit):
            data = editor.date().toString("MM/dd/yyyy")
            model.setData(index, data)
        else:
            super().setModelData(editor, model, index)
# create a mapper and point it to the clients_model
self.this_clients_model = a_clients_model
self.mapper = qtw.QDataWidgetMapper(self)
self.mapper.setModel(self.this_clients_model)
# self.mapper.setItemDelegate(qts.QSqlRelationalDelegate(self))
self.mapper.setItemDelegate(Delegate(self))
相关问题