Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Пытон от Январь 13, 2013, 18:12



Название: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 13, 2013, 18:12
Допустим используем контролы QLineEdit для редактирования полей FAM, IM, OT.
И как я должен указать лайнэдиту откуда брать данные?
Возможно ли вообще это? Запишет ли лайнэдит данные обратно в БД?

Как это реализуется?
Использую QtSql для соединения с SQLite. Могу вывести данные в таблицу на форме при помощи QtableView и QTableModel. В такой таблице-то всё преспокойно будет сохраняться сразу в БД. А мне надо форму с текстбоксами, комбобоксами и т.д.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Bepec от Январь 13, 2013, 18:42
Эммм.. слишком всё хорошо вы хотите.
И кроватку и матрас и одеяльце и девушку под бочок :)

нет, нету, нужно реализовывать самому через обычные запросы.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 13, 2013, 18:52
Как это реализуется?
Посмотри на QDataWidgetMapper и примеры его использования в связке с sql.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 13, 2013, 19:12
Спасибо. Попробую поискать. Ежели есть у кого примеры, не стесняйтесь, выкладывайте ссылочку.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 13, 2013, 19:14
Ежели есть у кого примеры, не стесняйтесь, выкладывайте ссылочку.
Прямо с Qt идут примеры. В разделе sql есть пример его использования. :)


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 13, 2013, 19:49
Да? Может у меня какая-то уже старая версия?
У меня там лишь примеры по connection, tablemodel, relationtablemodel, ещё чего-то парочку. Про маппер ничего там не видел.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 13, 2013, 19:53
Да? Может у меня какая-то уже старая версия?
У меня там лишь примеры по connection, tablemodel, relationtablemodel, ещё чего-то парочку. Про маппер ничего там не видел.
sqlwidgetmapper


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: ksk- от Январь 13, 2013, 22:09
Я бы использовал питоний модуль "sqlite3" для работы с БД. ИМХО, с ним проще. Ну это я так, к слову. )))


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 12:43
Я бы использовал питоний модуль "sqlite3" для работы с БД. ИМХО, с ним проще. Ну это я так, к слову. )))
И париться с реализацией заброса данных в таблицу, сохранения данных из таблицы?

Код
Python
from PyQt4 import QtGui, QtCore, QtSql
import os.path
 
class mainform(QtGui.QWidget):
   def __init__(self):
       QtGui.QWidget.__init__(self)
       self.resize(600, 700)
       self.con = QtSql.QSqlDatabase.addDatabase("QSQLITE", "Base")
       self.con.setDatabaseName("./SQLiteBase/PyQt4DB.s3db")
 
       self.OpenOrCreateDB()
 
       self.mainLayout = QtGui.QVBoxLayout()
       self.setLayout(self.mainLayout)
 
       self.btnFill = QtGui.QPushButton("Заполнить БД некоторыми данными")
       self.mainLayout.addWidget(self.btnFill)
       self.btnFill.clicked.connect(self.Fill_View_With_Some_Values)
 
       self.model = QtSql.QSqlRelationalTableModel(None, self.con)
       self.model.setTable('thirst')
       self.typeindex = self.model.fieldIndex("type")
       self.model.setRelation(self.typeindex, QtSql.QSqlRelation("second", "type", "text"))
       self.model.select()      
 
       self.view1 = QtGui.QTableView()
       self.mainLayout.addWidget(self.view1)
       self.view1.setModel(self.model)
       self.view1.setItemDelegate(QtSql.QSqlRelationalDelegate(self.view1))
 
       self.view2 = QtGui.QTableView()
       self.mainLayout.addWidget(self.view2)
       self.view2.setModel(self.model)
 
       self.txtBoxTovar = QtGui.QLineEdit()
       self.mainLayout.addWidget(self.txtBoxTovar)
 
       self.comboBoxType = QtGui.QComboBox()      
       self.mainLayout.addWidget(self.comboBoxType)
 
       self.btnNew = QtGui.QPushButton("Новая запись")
       self.mainLayout.addWidget(self.btnNew)
 
       self.mapper = QtGui.QDataWidgetMapper()
       self.mapper.setModel(self.model)
       self.mapper.setItemDelegate(QtSql.QSqlRelationalDelegate())
       self.mapper.addMapping(self.txtBoxTovar, 1)
       self.comboBoxType.setModel(self.model)
       self.comboBoxType.setModelColumn(self.model.fieldIndex("text"))
       self.mapper.addMapping(self.comboBoxType, 2, 'text')
       self.mapper.toFirst()      
 
 
   def Fill_View_With_Some_Values(self):
       query = QtSql.QSqlQuery(self.con)
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Potato', 1)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Apple', 2)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Juice', 3)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Nuts', 4)")
       self.model.select()
 
 
 
   def OpenOrCreateDB(self):
 
 
       ThisIsNewBase = False
       if not os.path.exists("./SQLiteBase/PyQt4DB.s3db"): ThisIsNewBase = True
 
 
       if not self.con.open():
           print ("БД не открылась!")
       else:
           print ("БД открыта")
           if ThisIsNewBase == True: self.Create_Structure_of_DB()
 
 
   def Create_Structure_of_DB(self):
       query = QtSql.QSqlQuery(self.con)
       query.exec("CREATE TABLE thirst ("
                  "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                  "tovar VARCHAR(20) NOT NULL, "
                  "type INTEGER NOT NULL"
                  ")")
       query.exec("CREATE TABLE second ("
                  "type INTEGER, "
                  "text VARCHAR(50)"
                  ")")
       query.exec("INSERT INTO second VALUES(1, 'Бяка')")
       query.exec("INSERT INTO second VALUES(2, 'Кака')")
       query.exec("INSERT INTO second VALUES(3, 'Добро')")
       query.exec("INSERT INTO second VALUES(4, 'Благо')")
 
if __name__=="__main__":
   import sys
   app = QtGui.QApplication(sys.argv)
   form1 = mainform()
   form1.setWindowTitle("Работа с БД при помощи PyQt4")
   form1.show()
   sys.exit(app.exec_())
 
 

Скажите, почто мне комбобокс выдаёт не список из таблицы-справочника second, а все записи из таблицы thirst (столбец type) с соответствующими им значениями из таблицы second?


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 16:47
Никто не знает?


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 14, 2013, 16:52
Никто не знает?

А ты ему что назначаешь?
Код
Python
       self.comboBoxType.setModel(self.model)
       self.comboBoxType.setModelColumn(self.model.fieldIndex("text"))
 


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 18:03
Может я и тормоз, но ЧТО я ему должен назначить и как?

Надо чтобы он брал соответствие из поля text из таблицы second. Соответствие ищется по одноимённым полям type в двух таблицах.

Кстати, чтобы лучше понять о чём я написал выше, в программе нужно дважды добавить данные кнопкой на форме. Тогда комбобокс будет показывать восемь строк, хотя в таблице second их только четыре! Он мне, получается, выдаёт весь столбец поля из таблицы thirst. А мне надо, чтобы выдавал список из таблицы second.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 14, 2013, 18:16
Может я и тормоз, но ЧТО я ему должен назначить и как?
Ты написал, что бы модель взяла данные из таблицы thirs и разименовала поле type, подставив вместо индекса его название (берется из таблицы second).
И эту модель ты устанавливаешь в комбобокс.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 18:19
Дык, что мне сделать-то, чтобы комбобокс предлагал для выбора только данные из таблицы second? Но при этом комбобокс должен показывать выбранным именно то значение, которое находится в текущей строке таблицы thirst.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 14, 2013, 18:29
Дык, что мне сделать-то, чтобы комбобокс предлагал для выбора только данные из таблицы second? Но при этом комбобокс должен показывать выбранным именно то значение, которое находится в текущей строке таблицы thirst.
Установить модель с таблицей second. :)
Посмотри пример Qt еще раз, там для комбобокса устанавливается отдельная модель.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 18:53
Эх, и как же я, болезный, состыкую-то обе модели в тандем...


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Old от Январь 14, 2013, 19:07
Эх, и как же я, болезный, состыкую-то обе модели в тандем...
А в чем проблема?
Данные для комбобокса, будут браться из таблицы second (их будет 4), а текущий индекс будет браться из соответствующего поля таблицы thirst.
Пример Qt делает ровно тоже. Просто модель для second достается с помощью метода:
QSqlTableModel * QSqlRelationalTableModel::relationModel ( int column ) const [virtual]


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 14, 2013, 19:26
Моя не понимайт синтаксис С.  :-[


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 15, 2013, 06:50
Код
Python
from PyQt4 import QtGui, QtCore, QtSql
import os.path
 
class mainform(QtGui.QWidget):
   def __init__(self):
       QtGui.QWidget.__init__(self)
       self.resize(600, 700)
       self.con = QtSql.QSqlDatabase.addDatabase("QSQLITE", "Base")
       self.con.setDatabaseName("./SQLiteBase/PyQt4DB.s3db")
 
       self.OpenOrCreateDB()
 
       self.mainLayout = QtGui.QVBoxLayout()
       self.setLayout(self.mainLayout)
 
       self.btnFill = QtGui.QPushButton("Заполнить БД некоторыми данными")
       self.mainLayout.addWidget(self.btnFill)
       self.btnFill.clicked.connect(self.Fill_View_With_Some_Values)
 
       #реляционная модель данных
       self.model = QtSql.QSqlRelationalTableModel(None, self.con) #создание
       self.model.setTable('thirst') #выбор таблицы для модели
       self.typeindex = self.model.fieldIndex("type") #объект содержит индекс столбца по его имени
       self.model.setRelation(self.typeindex, QtSql.QSqlRelation("second", "type", "text")) #указание связи
       self.model.select() #заполнение модели данными из БД
       # столбец 2(type) будет заполнен соответствующими значениями поля text из таблицы second
 
       #создание виджета таблицы (вида, отображения)
       self.view1 = QtGui.QTableView() # сам вид
       self.mainLayout.addWidget(self.view1) # добавляем его к контейнеру
       self.view1.setModel(self.model) # указываем какую модель использовать таблице
       self.view1.setItemDelegate(QtSql.QSqlRelationalDelegate(self.view1)) # создаём делегат
 
       #эта таблица служит лишь для того, чтобы показать, что разные таблицы могут использовать одну модель
       self.view2 = QtGui.QTableView()
       self.mainLayout.addWidget(self.view2)
       self.view2.setModel(self.model)
 
       #текстбокс для ввода товара
       self.txtBoxTovar = QtGui.QLineEdit()
       self.mainLayout.addWidget(self.txtBoxTovar)
 
       #Комбобокс для ввода типа товара
       self.comboBoxType = QtGui.QComboBox()      
       self.mainLayout.addWidget(self.comboBoxType)
 
       #кнопка для добавления строки в БД
       self.btnNew = QtGui.QPushButton("Новая запись")
       self.mainLayout.addWidget(self.btnNew)
 
 
       # создаём модель для комбобокса
       self.relModel = self.model.relationModel(self.typeindex) # модель для маппера
       self.comboBoxType.setModel(self.relModel)
       self.comboBoxType.setModelColumn(self.relModel.fieldIndex("text"))
       # создаём маппер (Он нужен для связывания полей таблицы БД и контролов)
       self.mapper = QtGui.QDataWidgetMapper() # сам маппер
       self.mapper.setModel(self.relModel)
       self.mapper.setItemDelegate(QtSql.QSqlRelationalDelegate(self)) #взял из примера, не понимаю на кой оно надо!
       self.mapper.addMapping(self.comboBoxType, self.typeindex)
 
 
       #self.mapper.addMapping(self.txtBoxTovar, 1)
 
 
 
       self.mapper.toFirst()      
 
 
   def Fill_View_With_Some_Values(self):
       query = QtSql.QSqlQuery(self.con)
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Potato', 1)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Apple', 2)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Juice', 3)")
       query.exec("INSERT INTO thirst (tovar, type) VALUES ('Nuts', 4)")
       self.model.select()
 
 
 
   def OpenOrCreateDB(self):
 
 
       ThisIsNewBase = False
       if not os.path.exists("./SQLiteBase/PyQt4DB.s3db"): ThisIsNewBase = True
 
 
       if not self.con.open():
           print ("БД не открылась!")
       else:
           print ("БД открыта")
           if ThisIsNewBase == True: self.Create_Structure_of_DB()
 
 
   def Create_Structure_of_DB(self):
       query = QtSql.QSqlQuery(self.con)
       query.exec("CREATE TABLE thirst ("
                  "id INTEGER PRIMARY KEY AUTOINCREMENT, "
                  "tovar VARCHAR(20) NOT NULL, "
                  "type INTEGER NOT NULL"
                  ")")
       query.exec("CREATE TABLE second ("
                  "type INTEGER, "
                  "text VARCHAR(50)"
                  ")")
       query.exec("INSERT INTO second VALUES(1, 'Бяка')")
       query.exec("INSERT INTO second VALUES(2, 'Кака')")
       query.exec("INSERT INTO second VALUES(3, 'Добро')")
       query.exec("INSERT INTO second VALUES(4, 'Благо')")
 
if __name__=="__main__":
   import sys
   app = QtGui.QApplication(sys.argv)
   form1 = mainform()
   form1.setWindowTitle("Работа с БД при помощи PyQt4")
   form1.show()
   sys.exit(app.exec_())

Переписал код. Теперь комбобокс правильно показывает мне только четыре значения из таблицы second, вот только отныне он живёт сам по себе и никак не согласовывается с таблицей thirst! Он просто показывает список из таблицы second.


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Пытон от Январь 15, 2013, 12:10
Маппер должен использовать model, а для комбобокса нужно создать свою модель:
self.relModel = self.model.relationModel(self.typeindex)
self.comboBoxType.setModel(self.relModel)


Название: Re: PyQT4 Как создать форму с контролами для редакт-я данных из полей строки БД.
Отправлено: Nimbus от Январь 20, 2013, 10:43
Пытон, привет собрат-питоновод. Я столкнулся с такой же проблемой. Поэтому приходится писать на PyQt4 своё собственное решение, чем сейчас и занимаюсь. Только я использую SQLAlchemy в качестве ORM. А также, взял подход обычной админки Django. Описываю модели в отдельном файлике в виде разных классов и накручиваю на них админские классы без реализации всякой бизнес-логики, лишь со списками какие поля и куда, связываю модели с этими классами, а дальше само разруливается (строятся формы списков и формы редактирования отдельных моделей) путём получения метаинформации из моделей. Соответственно нет никаких сырых SQL-запросов и вообще привязки к конкретной СУБД.
Могу потом как-нибудь поделиться с битбакета, если вынесу в отдельный пакет всё :-)