Главная страница

ээдд. Прохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен. Николай Прохоренок Владимир Дронов


Скачать 7.92 Mb.
НазваниеНиколай Прохоренок Владимир Дронов
Дата05.05.2023
Размер7.92 Mb.
Формат файлаpdf
Имя файлаПрохоренок_Н_А__Дронов_В_А_Python_3_и_PyQt_5_Разработка_приложен.pdf
ТипДокументы
#1111379
страница52 из 83
1   ...   48   49   50   51   52   53   54   55   ...   83

FIL={MS Access};DBQ=c:/work/data.mdb"); con3.open() con3.close()
Полное описание класса
QSqlDatabase приведено на странице https://doc.qt.io/qt-5/qsql database.html.
23.2. Получение сведений о структуре таблицы
PyQt позволяет получить некоторые сведения о структуре таблиц, хранящихся в базе: списки полей таблицы, параметры отдельного поля, индекса и ошибки, возникшей при ра- боте с базой.
23.2.1. Получение сведений о таблице
Сведения о структуре таблицы можно получить вызовом метода record()
класса
QSqlDatabase
. Эти сведения представляются экземпляром класса
QSqlRecord
Для получения сведений о полях таблицы используются следующие методы этого класса:
 count()
— возвращает количество полей в таблице;
 fieldName(<Индекс поля>)
— возвращает имя поля, имеющее заданный индекс, или пус- тую строку, если индекс некорректен;
 field(<Индекс поля>)
— возвращает сведения о поле (экземпляр класса
QSqlField
), чей индекс задан в качестве параметра;
 field(<Имя поля>)
— возвращает сведения о поле (экземпляр класса
QSqlField
), чье имя задано в качестве параметра;
 indexOf(<Имя поля>)
— возвращает индекс поля с указанным именем или
-1
, если тако- го поля нет. При поиске поля не учитывается регистр символов;
 contains(<Имя поля>)
— возвращает
True
, если поле с указанным именем существует, и
False
— в противном случае;
 isEmpty()
— возвращает
True
, если в таблице нет полей, и
False
— в противном случае.

536
Часть II. Библиотека PyQt 5
Полное описание класса
QSqlRecord приведено на странице https://doc.qt.io/qt-5/qsql record.html.
23.2.2. Получение сведений об отдельном поле
Сведения об отдельном поле таблицы возвращаются методом field()
класса
QSqlRecord
. Их представляет экземпляр класса
QSqlField
, поддерживающий следующие методы:
 name()
— возвращает имя поля;
 type()
— возвращает тип поля в виде одного из следующих атрибутов класса
QVariant
, объявленного в модуле
QtCore
(здесь приведен список лишь наиболее часто употребляе- мых типов — полный их список можно найти по адресу https://doc.qt.io/qt-5/qvariant- obsolete.html#Type-enum):

Invalid
— неизвестный тип;

Bool
— логический (
bool
);

ByteArray
— массив байтов (
QByteArray
, bytes
);

Char
— строка из одного символа (
str
);

Date
— значение даты (
QDate или datetime.date
);

DateTime
— значение даты и времени (
QDateTime или datetime.datetime
);

Double
— вещественное число (
float
);

Int и
LongLong
— целое число (
int
);

String
— строка (
str
);

Time
— значение времени (
QTime или datetime.time
);

UInt и
ULongLong
— положительное целое число (
int
);
 length()
— возвращает длину поля;
 precision()
— возвращает количество знаков после запятой для полей, хранящих веще- ственные числа;
 defaultValue()
— возвращает значение поля по умолчанию;
 requiredStatus()
— возвращает признак, является ли поле обязательным к заполнению, в виде одного из атрибутов класса
QSqlField
:

Required

1
— поле является обязательным к заполнению;

Optional

0
— поле не является обязательным к заполнению;

Unknown

-1
— определить признак обязательности заполнения поля не представля- ется возможным;
 isAutoValue()
— возвращает
True
, если значение в поле заносится автоматически (что может быть, например, у поля автоинкремента), и
False
— в противном случае;
 isReadOnly()
— возвращает
True
, если поле доступно только для чтения, и
False
— в противном случае.
Полное описание класса
QSqlField приведено на странице https://doc.qt.io/qt-5/qsqlfield.html.

Глава 23. Работа с базами данных
537 23.2.3. Получение сведений об индексе
Сведения о ключевом индексе, возвращаемые методом primaryIndex()
класса
QSqlDatabase
, представлены экземпляром класса
QSqlIndex
. Он наследует все методы класса
QSqlRecord
, тем самым позволяя узнать, в частности, список полей, на основе которых создан индекс.
Также он определяет следующие методы:
 name()
— возвращает имя индекса или пустую строку для ключевого индекса;
 isDescending(<Номер поля>)
— возвращает
True
, если поле с указанным номером в ин- дексе отсортировано по убыванию, и
False
— в противном случае.
Полное описание класса
QSqlIndex приведено на странице https://doc.qt.io/qt-5/qsqlindex.html.
23.2.4. Получение сведений об ошибке
Сведения об ошибке, возникшей при работе с базой данных, представляются экземпляром класса
QSqlError
. Выяснить, что за ошибка произошла и каковы ее причины, позволят сле- дующие методы вышеупомянутого класса:
 type()
— возвращает код ошибки в виде одного из следующих атрибутов класса
QSqlError
:

NoError

0
— никакой ошибки не возникло;

ConnectionError

1
— ошибка соединения с базой данных;

StatementError

2
— ошибка в коде SQL-запроса;

TransactionError

3
— ошибка в обработке транзакции;

UnknownError

4
— ошибка неустановленной природы.
Если код ошибки не удается определить, возвращается
-1
;
 text()
— возвращает полное текстовое описание ошибки (фактически — значения, воз- вращаемые методами databaseText()
и driverText()
, объединенные в одну строку);
 databaseText()
— возвращает текстовое описание ошибки, сгенерированное базой дан- ных;
 driverText()
— возвращает текстовое описание ошибки, сгенерированное драйвером базы данных, который входит в состав PyQt;
 nativeErrorCode()
— возвращает строковый код ошибки, специфический для выбранно- го формата баз данных.
Пример: con = QtSql.QSqlDatabase.addDatabase('QSQLITE') con.setDatabaseName('data.sqlite') if con.open():
# Работаем с базой данных else:
# Выводим текст описания ошибки print(con.lastError().text())
Полное описание класса
QSqlError можно найти на странице https://doc.qt.io/qt-5/qsql error.html.

538
Часть II. Библиотека PyQt 5 23.3. Выполнение SQL-запросов и получение их результатов
Класс
QSqlQuery позволяет выполнять SQL-запросы любого назначения: создания необхо- димых таблиц и индексов, добавления, изменения, удаления и, разумеется, выборки запи- сей. Это один из наиболее развитых механизмов работы с данными, предоставляемых PyQt.
П
РИМЕЧАНИЕ
Далее будут рассмотрены лишь наиболее часто используемые возможности класса
QSqlQuery
. Полное его описание приведено на странице https://doc.qt.io/qt-5/qsql query.html.
23.3.1. Выполнение запросов
Чтобы выполнить запрос к базе, сначала следует создать экземпляр класса
QSqlQuery
. Для этого используется один из следующих форматов вызова его конструктора:
QSqlQuery([][, db=QSqlDatabase()])
QSqlQuery()
QSqlQuery()
Первый формат позволяет сразу задать SQL-код, который следует выполнить, и немедленно запустить его на исполнение. Необязательный параметр db задает соединение с базой дан- ных, запрос к которой следует выполнить, — если он не указан, будет использоваться со- единение по умолчанию.
Второй формат создает пустой запрос, не содержащий ни SQL-кода, ни каких-либо прочих параметров, но позволяющий указать соединение к нужной базе данных. Третий запрос создает копию запроса, переданного в параметре.
Для выполнения запросов используются следующие методы класса
QSqlQuery
:
 exec()
— немедленно выполняет переданный в параметре SQL-код. Если по- следний был успешно выполнен, возвращает
True и переводит запрос в активное состоя- ние, в противном случае возвращает
False
. Пример использования этого метода показан в листинге 23.2.
Листинг 23.2. Использование метода exec() from PyQt5 import QtWidgets, QtSql import sys app = QtWidgets.QApplication(sys.argv) con = QtSql.QSqlDatabase.addDatabase('QSQLITE') con.setDatabaseName('data.sqlite') con.open()
# Проверяем, есть ли в базе данных таблица good, и, если таковой нет,
# создаем ее SQL-командой CREATE TABLE if 'good' not in con.tables(): query = QtSql.QSqlQuery() query.exec("create table good(id integer primary key autoincrement,
 goodname text, goodcount integer) ") con.close()

Глава 23. Работа с базами данных
539
С
ОВЕТ
Метод exec() следует использовать в тех случаях, если SQL-запрос не принимает пара- метров. В противном случае рекомендуется применять методы, рассмотренные далее.
 prepare()
— подготавливает SQL-запрос к выполнению. Применяется, если
SQL-запрос содержит параметры. Параметры в коде запроса могут быть заданы либо в стиле ODBC (вопросительными знаками), либо в стиле Oracle (символьными обозна- чениями, предваренными знаком двоеточия). Метод возвращает
True
, если SQL-запрос был успешно подготовлен, и
False
— в противном случае;
 exec_()
— выполняет подготовленный ранее запрос. Возвращает
True
, если запрос был успешно выполнен, и
False
— в противном случае;
 addBindValue(<Значение параметра>[, paramType=In])
— задает значение очередного по счету параметра: так, первый вызов этого метода задает значение для первого параметра, второй вызов — для второго и т. д. Необязательный параметр paramType указывает тип параметра — здесь практически всегда используется атрибут
In класса
QSql
, означаю- щий, что этот параметр служит для занесения значения в базу.
В листинге 23.3 приведен пример использования методов prepare()
, addBindValue()
и exec_()
Листинг 23.3. Использование методов prepare(), addBindValue() и exec_() 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()
# Добавляем в только что созданную таблицу good запись,
# используя SQL-команду INSERT query.prepare("insert into good values(null, ?, ?)") query.addBindValue('Дискета') query.addBindValue(10) query.exec_() con.close()
 bindValue(<Номер параметра>, <Значение параметра>[, paramType=In])
— задает зна- чение для параметра с указанным порядковым номером (листинг 23.4).
Листинг 23.4. Использование метода bindValue() для задания параметров по их порядковым номерам 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()

540
Часть II. Библиотека PyQt 5 query.prepare("insert into good values(null, ?, ?)") query.bindValue(0, 'Компакт-диск') query.bindValue(1, 5) query.exec_() con.close()
 bindValue(<Обозначение параметра>, <Значение параметра>[, paramType=In])
— задает значение для параметра с указанным символьным обозначением (листинг 23.5).
Листинг 23.5. Использование метода bindValue() для задания параметров по их символьным обозначениям 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.prepare("insert into good values(null, :name, :count)") query.bindValue(':name', 'Флеш-накопитель') query.bindValue(':count', 20) query.exec_() con.close()
 execBatch([mode=ValuesAsRows])
— если в вызове метода addBindValue()
или bindValue()
в качестве значения параметра был указан список, выполнит подготовленный запрос.
Необязательный параметр mode позволяет указать, как будут интерпретироваться от- дельные элементы списка. В настоящее время в качестве его значения для всех форматов баз данных поддерживается лишь атрибут
ValuesAsRows класса
QSqlQuery
, говорящий, что подготовленный запрос должен быть выполнен столько раз, сколько элементов при- сутствует в списке, при этом на каждом выполнении запроса в его код подставляется очередной элемент списка.
Метод возвращает
True
, если запрос был успешно выполнен, и
False
— в противном случае.
Листинг 23.6 представляет пример добавления в таблицу сразу нескольких записей с применением метода execBatch()
Листинг 23.6. Использование метода execBatch() для добавления в таблицу сразу нескольких записей 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.prepare("insert into good values(null, :name, :count)")

Глава 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


написать администратору сайта