ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 05.12.2023
Просмотров: 863
Скачиваний: 3
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
Глава 23. Работа с базами данных
541 lst1 = ['Бумага офисная', 'Фотобумага', 'Картридж'] lst2 = [15, 8, 3] query.bindValue(':name', lst1) query.bindValue(':count', lst2) query.execBatch() con.close()
setForwardOnly(<Флаг>)
— если передано значение
True
, по результату запроса можно будет перемещаться только «вперед», т. е. от начала к концу. Такой режим выполнения запроса существенно сокращает потребление системных ресурсов. Этот метод должен быть вызван перед выполнением запроса, который возвращает результат: query.prepare("select * from good order by goodname") query.setForwardOnly(True) query.exec_()
23.3.2. Обработка результатов выполнения запросов
Если был выполнен запрос на выборку данных (SQL-команда
SELECT
), следует получить результат его выполнения. Для этого мы используем методы класса
QSqlQuery
, описанные в этом разделе.
Запрос на выборку данных поддерживает особый внутренний указатель, указывающий на запись результата, содержимое которой в настоящее время доступно для получения. Однако сразу после выполнения запроса этот указатель хранит неопределенное значение, не иден- тифицирующее никакую реальную запись. Поэтому перед собственно выборкой данных необходимо позиционировать этот указатель на нужную запись:
first()
— позиционирует указатель запроса на первую запись результата. Возвращает
True
, если позиционирование прошло успешно, и
False
— в противном случае;
next()
— позиционирует указатель запроса на следующую запись результата или на первую запись, если этот метод был вызван сразу после выполнения запроса. Возвраща- ет
True
, если позиционирование прошло успешно, и
False
— в противном случае;
previous()
— позиционирует указатель запроса на предыдущую запись результата или на последнюю запись, если указатель в текущий момент находится за последней записью. Возвращает
True
, если позиционирование прошло успешно, и
False
— в про- тивном случае;
last()
— позиционирует указатель запроса на последнюю запись результата. Возвраща- ет
True
, если позиционирование прошло успешно, и
False
— в противном случае;
seek(<Номер записи>[, relative=False])
— позиционирует указатель на запись с ука- занным номером (нумерация записей начинается с нуля). Если необязательным парамет- ром relative передано значение
True
, то позиционирование выполняется относительно текущей записи: положительные значения вызывают смещение указателя «вперед»
(к концу), а отрицательные — «назад» (к началу). Возвращает
True
, если позициониро- вание прошло успешно, и
False
— в противном случае;
isValid()
— возвращает
True
, если внутренний указатель указывает на какую-либо запись, и
False
, если он имеет неопределенное значение;
at()
— возвращает номер записи, на которую указывает внутренний указатель запроса;
542
Часть II. Библиотека PyQt 5
size()
— возвращает количество записей, возвращенных в результате выполнения за- проса, или
-1
, если этот запрос не выполнял выборку данных.
Для собственно выборки данных следует применять описанные далее методы:
value(<Индекс поля>)
— возвращает значение поля текущей записи с заданным индек- сом. Поля нумеруются в том порядке, в котором они присутствуют в таблице базы или в SQL-коде запроса;
value(<Имя поля>)
— возвращает значение поля текущей записи с заданным именем;
isNull(<Индекс поля>)
— возвращает
True
, если в поле с указанным индексом нет зна- чения, и
False
— в противном случае;
isNull(<Имя поля>)
— возвращает
True
, если в поле с указанным именем нет значения, и
False
— в противном случае;
record()
— если внутренний указатель установлен на какую-либо запись, возвращает сведения об этой записи, в противном случае возвращаются сведения о самой таблице.
Возвращаемым результатом является экземпляр класса
QSqlRecord
;
isSelect()
— возвращает
True
, если был выполнен запрос на выборку данных, и
False
, если исполнялся запрос иного рода.
В листинге 23.7 приведен код, извлекающий данные из таблицы good созданной ранее базы данных и выводящий их на экран.
Листинг 23.7. Выборка данных из базы from PyQt5 import QtWidgets, QtSql import sys app = QtWidgets.QApplication(sys.argv) con = QtSql.QSqlDatabase.addDatabase('QSQLITE') con.setDatabaseName('data.sqlite') con.open() query = QtSql.QSqlQuery() query.exec("select * from good order by goodname") lst = [] if query.isActive(): query.first() while query.isValid(): lst.append(query.value('goodname') + ': ' +
str(query.value('goodcount')) + ' шт.') query.next() for p in lst: print(p) con.close()
Результат выполнения этого кода:
Бумага офисная: 15 шт.
Дискета: 10 шт.
Картридж: 3 шт.
Компакт-диск: 5 шт.
Флеш-накопитель: 20 шт.
Фотобумага: 8 шт.
Глава 23. Работа с базами данных
543 23.3.3. Очистка запроса
После первого выполнения метода exec()
, exec_()
или execBatch()
1 ... 48 49 50 51 52 53 54 55 ... 83
) запрос переходит в активное состояние. Это значит, что выполнить любую другую SQL-команду с его по- мощью невозможно.
Метод isActive()
класса
QSqlQuery возвращает
True
, если запрос находится в активном со- стоянии. Если же запрос неактивен, метод возвращает
False
Если один и тот же экземпляр класса
QSqlQuery планируется использовать для выполнения нескольких SQL-команд, перед выполнением новой команды следует сбросить его, переве- дя тем самым в неактивное состояние и освободив занимаемые им системные ресурсы. Это выполняется вызовом метода clear()
: query = QtSql.QSqlQuery() query.exec("select * from good order by goodname")
# Обрабатываем результат запроса query.clear() query.exec("select count(*) as cnt from good")
# Работаем с новым запросом
23.3.4. Получение служебных сведений о запросе
Класс
QSqlQuery позволяет также получить всевозможные служебные сведения о запросе.
Для этого применяются следующие методы:
numRowsAffected()
— возвращает количество записей, обработанных в процессе выпол- нения запроса, или
-1
, если это количество не удается определить. Для запросов выбор- ки данных возвращает
None
— в этом случае следует вызывать метод size()
;
lastInsertId()
— возвращает идентификатор последней добавленной записи. Если за- прос не добавлял записи, или если формат базы данных не позволяет определить иден- тификатор последней добавленной записи, возвращает
None
;
lastError()
— возвращает экземпляр объекта
QSqlError
, описывающий последнюю возникшую в базе данных ошибку;
executedQuery()
— возвращает SQL-код последнего выполненного запроса или пустую строку, если никакой запрос еще не был выполнен;
lastQuery()
— возвращает код последнего выполненного запроса или пустую строку, если никакой запрос еще не был выполнен. Отличается от метода executedQuery()
тем, что все именованные параметры (заданные символьными обозначениями) в возвращае- мом SQL-коде заменяются вопросительными знаками;
boundValue(<Номер параметра>)
— возвращает значение параметра запроса с указанным номером;
boundValue(<Обозначение параметра>)
— возвращает значение параметра запроса с ука- занным символьным обозначением;
boundValues()
— возвращает словарь, ключами элементов которого служат символьные обозначения параметров, а значениями элементов — значения этих параметров. Если параметры обозначены вопросительными знаками, в качестве ключей используются произвольные строки вида
:a для первого параметра,
:bb для второго и т. д.
544
Часть II. Библиотека PyQt 5 23.4. Модели, связанные с данными
Очень часто данные, хранящиеся в базе, выводятся на экран с применением таких компо- нентов, как списки или таблицы (подробно списки и таблицы описаны в главе 22). Для этих случаев PyQt предоставляет два класса-модели, извлекающие данные напрямую из базы.
23.4.1. Модель, связанная с SQL-запросом
Если требуется вывести на экран данные, извлеченные в результате выполнения SQL- запроса, и эти данные не требуется редактировать, имеет смысл использовать класс
QSqlQueryModel
. Он представляет модель, связанную с SQL-запросом. Иерархия наследова- ния этого класса:
QObject – QAbstractItemModel – QAbstractTableModel – QSqlQueryModel
Конструктор класса:
<Объект> = QSqlQueryModel([parent=None])
Класс
QSqlQueryModel поддерживает следующие методы (здесь приведен их сокращенный список, а полный список методов этого класса доступен на страницах https://doc.qt.io/ qt-5/qsqlquerymodel.html и https://doc.qt.io/qt-5/qabstractitemmodel.html):
setQuery(<Код запроса>[, db=QSqlDatabase()])
— задает код запроса для модели. Не- обязательный параметр db задает соединение с базой данных, запрос к которой следует выполнить, — если он не указан, будет использоваться соединение по умолчанию;
query()
— возвращает код запроса, заданного для модели;
record()
— возвращает экземпляр класса
QSqlRecord
, представляющий сведения о струк- туре результата запроса;
record(<Индекс строки>)
— возвращает экземпляр класса
QSqlRecord
, представляющий сведения о записи, которая соответствует строке модели с указанным индексом;
lastError()
— возвращает экземпляр объекта
QSqlError
, описывающий последнюю возникшую в базе данных ошибку;
index(<Строка>, <Столбец>[, parent=QModelIndex()])
— возвращает индекс (экземпляр класса
QModelIndex
) элемента модели, находящегося на пересечении строки и столбца с указанными индексами. Необязательный параметр parent позволяет задать элемент верхнего уровня для искомого элемента — если таковой не задан, будет выполнен поиск элемента на самом верхнем уровне иерархии;
data(
— возвращает данные, хранимые в указанной в параметре role роли элемента, на который ссылается индекс
;
rowCount([parent=QModelIndex()])
— возвращает количество элементов в модели. Не- обязательный параметр parent указывает элемент верхнего уровня, при этом будет воз- вращено количество вложенных в него элементов. Если параметр не задан, возвращается количество элементов верхнего уровня иерархии;
sort(<Индекс столбца>[, order=AscendingOrder])
— производит сортировку. Если во втором параметре указан атрибут
AscendingOrder класса
QtCore.Qt
, сортировка произво- дится в прямом порядке, а если
DescendingOrder
— в обратном;
setHeaderData(<Индекс>, <Ориентация>, <Значение>[, role=EditRole])
— задает зна- чение для указанной роли заголовка. В первом параметре указывается индекс строки или
Глава 23. Работа с базами данных
545 столбца, а во втором — ориентация (атрибут
Horizontal или
Vertical класса
QtCore.Qt
).
Метод возвращает значение
True
, если операция успешно выполнена;
headerData(<Индекс>, <Ориентация>[, role=DisplayRole])
— возвращает значение, со- ответствующее указанной роли заголовка. В первом параметре указывается индекс стро- ки или столбца, а во втором — ориентация.
Рассмотрим пример, выводящий данные из созданной нами ранее базы с помощью компо- нента таблицы (листинг 23.8).
Листинг 23.8. Использование модели, привязанной к SQL-запросу from PyQt5 import QtCore, QtWidgets, QtSql import sys app = QtWidgets.QApplication(sys.argv) window = QtWidgets.QTableView() window.setWindowTitle("QSqlQueryModel")
# Устанавливаем соединение с базой данных con = QtSql.QSqlDatabase.addDatabase('QSQLITE') con.setDatabaseName('data.sqlite') con.open()
# Создаем модель sqm = QtSql.QSqlQueryModel(parent=window) sqm.setQuery('select * from good order by goodname')
# Задаем заголовки для столбцов модели sqm.setHeaderData(1, QtCore.Qt.Horizontal, 'Название') sqm.setHeaderData(2, QtCore.Qt.Horizontal, 'Кол-во')
# Задаем для таблицы только что созданную модель window.setModel(sqm)
# Скрываем первый столбец, в котором выводится идентификатор window.hideColumn(0) window.setColumnWidth(1, 150) window.setColumnWidth(2, 60) window.resize(260, 160) window.show() sys.exit(app.exec_())
23.4.2. Модель, связанная с таблицей
Если необходимо дать пользователю возможность редактировать данные, хранящиеся в базе, следует использовать класс
QSqlTableModel
. Он представляет модель, связанную не- посредственно с указанной таблицей базы данных. Иерархия наследования:
QObject – QAbstractItemModel – QAbstractTableModel – QSqlQueryModel –
QSqlTableModel
Конструктор класса:
<Объект> = QSqlTableModel([parent=None][, db=QSqlDatabase()])
Необязательный параметр db задает соединение с базой данных, запрос к которой следует выполнить, — если он не указан, будет использоваться соединение по умолчанию.
546
Часть II. Библиотека PyQt 5
Класс
QSqlTableModel наследует все методы из класса
QSqlQueryModel
(см. разд. 23.4.1) и в дополнение к ним определяет следующие наиболее полезные для нас методы (полный их список приведен на странице https://doc.qt.io/qt-5/qsqltablemodel.html):
setTable(<Имя таблицы>)
— задает таблицу, данные из которой будут представлены в модели. Отметим, что этот метод лишь выполняет получение из базы данных структу- ры указанной таблицы, но не загружает сами эти данные;
tableName()
— возвращает имя таблицы, заданной для модели;
setSort(<Индекс столбца>, <Порядок сортировки>)
— задает сортировку данных. Если во втором параметре указан атрибут
AscendingOrder класса
QtCore.Qt
, сортировка про- изводится в прямом порядке, а если
DescendingOrder
— в обратном;
setFilter(<Условие фильтрации>)
— задает условие для фильтрации данных в виде строки в том формате, который применяется в SQL-команде
WHERE
;
filter()
— возвращает строку с фильтром, заданным для модели;
select()
— считывает в модель данные из заданной ранее таблицы с учетом указанных параметров сортировки и фильтрации. Возвращает
True
, если считывание данных про- шло успешно, и
False
— в противном случае: stm = QtSql.QSqlTableModel(parent=window) stm.setTable('good') stm.setSort(1, QtCore.Qt.DescendingOrder) stm.setFilter('goodcount > 2') stm.select()
Метод является слотом;
setEditStrategy(<Режим редактирования>)
— указывает режим редактирования данных в модели. В качестве параметра используется один из атрибутов класса
QSqlTableModel
:
•
OnFieldChange
—
0
— все изменения переносятся в базу данных немедленно;
•
OnRowChange
—
1
— изменения переносятся в базу лишь после того, как пользователь перейдет на другую строку;
•
OnManualSubmit
—
2
— изменения переносятся в базу только после вызова метода submit()
или submitAll()
;
insertRow(<Индекс>[, parent=QModelIndex()])
— вставляет пустую запись в позицию, заданную первым параметром. Возвращает значение
True
, если запись была успешно добавлена, и
False
— в противном случае;
insertRows(<Индекс>, <Количество>[, parent=QModelIndex()])
— вставляет указанное количество пустых записей в позицию, заданную первым параметром. Возвращает зна- чение
True
, если записи были успешно добавлены, и
False
— в противном случае;
setData(
— задает значение для роли role поля записи, на которое указывает индекс
. Возвращает значение
True
, если данные были успешно занесены в запись, и
False
— в противном случае;
removeRow(<Индекс>[, parent=QModelIndex()])
— удаляет запись с указанным индексом.
Возвращает значение
True
, если запись была успешно удалена, и
False
— в противном случае;
removeRows(<Индекс>, <Количество>[, parent=QModelIndex()])
— удаляет указанное количество записей, начиная с записи с указанным индексом. Возвращает значение
True
, если записи были успешно удалены, и
False
— в противном случае;