Заметки Python #26: Базы данных

Обучение

Со временем наше приложение обрастает всё большим набором функций, а значит — объем передаваемый, принимаемых, обрабатываемых данных растет.

И их нужно где-то хранить

Базы данных в Python

Работа с базой данных в питоне строится на двух подходах: использование протокола Python DB-API и библиотеками ORM (англ. Object-Relational Mapping, рус. объектно-реляционное отображение, или преобразование). Для работы с протоколом, в большинстве случаев, используется реляционную СУБД SQLite, поэтому необходимо знать синтаксис SQL-запросов. Приоритетным решением является именно ORM, так как позволяет работать без создания SQL-запросов, используя классы-посредники. Например, так работает популярный фреймворк Django. Там такими классами являются модели. Модель — представление с помощью языка питон некой таблицы

Python DB API

Протокол про которому работают модули с базой данных. Список операций

  1. Connection — сначала нужно подключиться.
  2. Cursor — Объект соединения с БД
  3. Execute — выполнение запроса
  4. Fetchall — получение данных
  5. Commit — подтверждение запроса (транзакции)

Библиотека sqllite3

Модуль sqlite3 — есть в питоне. Это стандартная библиотека. С sqllite3 можно работать через браузер баз данных (например, sqllite studio).

Для начала мы должны импортировать библиотеку — import sqlite3. Далее создать файл (т.к. у нас файловая база данных). Это делается с помощью конструкции sqlfile = os.path.join(os.path.dirname(__file__), «sample.sqlite»). Он создаться в той же директории, с которой мы запускаем скрипт. Если база с таким именем не существует — скрипт создаст его. Далее коннектимся к ней — conn = sqlite3.connect(sqlfile). Создаем специальный объект курсор: cursor = conn.cursor(), который будет выступать «посредником» между нами и БД — он делает запросы и получает ответы (чтение/запись).

Чтобы выполнить запрос нужно выполнить привязку к объекту cursor. Например, команда с обычным SQL-синтаксисом cursor.execute(«SELECT FIO FROM Students ORDER BY FIO LIMIT 3») — выполнит чтение записи в БД.  Получение результатов — results = cursor.fetchall(). Fetchall- извлечение всех данных по вашему запросу.

Если бы мы использовали в SQL-запросе слово INSERT, то вы бы вставили нужные значения в БД. В таком случае, нам бы понадобилось «закоммитить», подтвердить запрос инструкцией conn.commit(). Для того, чтобы выполнить несколько запросов к базе, необходимо использовать cursor.executescript(). Это позволит не захламлять код. В конце закрываем соединение с БД — conn.close()

Итого вы имеем такой синтаксис:

import sqlite3
import os.path

sqlfile = os.path.join(os.path.dirname(__file__), «demo.sqlite»)

conn = sqlite3.connect(sqlfile)

cursor = conn.cursor()

cursor.execute(«SELECT FIO FROM Students ORDER BY FIO LIMIT 3»)

results = cursor.fetchall()

cursor.execute(«insert into FIO values (‘Andrey’, ‘Bulkin’) «)

conn.commit()

conn.close()

Подстановка значений в запрос

Подстановка — это шаблон запроса. Постановка может реализовать запрос, но не зная значения, мы можем поставить в него знак вопроса — данные еще не определены, но они скоро будут туда вставлены из связанной переменной.

cursor.execute(«SELECT FIO FROM Students ORDER BY FIO LIMIT ?», (‘variable’))

Чтобы подставить множество значений в запрос, то необходимо использовать cursor.executemany

new_FIO = [
(‘Kor’,),
(‘Tor’,),
(‘Var’,),

cursor.executemany(«insert into FIO values (Null, ?);», new_FIO)

Чтобы получить результаты используем cursor.fetchone:

cursor.execute(«SELECT FIO FROM Students ORDER BY FIO LIMIT 3»)

print(cursor.fetchone()) # (‘Kor’,)
print(cursor.fetchone()) # (‘Tor’,)
print(cursor.fetchone()) # (‘Var’,)

Можно запустить перебор записей, если использовать курсор как итератор. Полученный результат будет список кортежей.

for row in cursor.execute(‘SELECT FIO FROM Students ORDER BY FIO LIMIT 3’):
print(row)

Чтобы запустить обработку исключений используем try/except

try:
cursor.execute(sql_base)
res = cursor.fetchall()
except sqlite3.DatabaseError as err:
print(«Error: «, err)
else:
conn.commit()

ORM SQLAlchemy

Чтобы не выполнять сложные SQL-запросы, можно использовать ORM и выполнять обращение к базе через обычный синтаксис языка Python. Таким образом, ORM будет посредником между программой и базой данных, а класс — это шаблон для таблиц. SQLAlchemy — одна из самых популярных ORM для питона. Её нужно установить дополнительно (не входит в стандартный набор модулей Python). Как это работает?

Для начала engine = create_engine(‘sqlite:///:memory:’, echo=True) — команда, отвечающая за подключение к базе данных, которая хранится в памяти. echo=True — это часть, которая разрешает логгирование через модуль logging.

Далее пишем таблицы с помощью вызова MetaData(). Это конструктор, который описывает вашу БД. Экземпляр этого класса необходимо создать, а затем прописать его в таблице.

metadata = MetaData()
heroes_table = Table(‘Marvel’, metadata, # указываем название таблицы FIO
Column(‘id’, Integer, primary_key=True),# Конструктор для полей с обязательным праймари кей
Column(‘name’, String),
Column(‘fullname’, String),
Column(‘city’, String)

Чтобы создать наши таблицы используется команда экземпляра metadata — metadata.create_all(engine). В качестве аргумента указывается объект engine. Теперь нужно создать наше связующее звено — «класс-посредник». Все его параметры будут соответствовать колонкам нашей таблицы. Так же необходимо выполнить переопределение функции __repr__(представление экземпляра класса) — можно сделать через .format или f-строки.

class Character:
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.team= team

def __repr__(self):
return «<Character(‘%s’,’%s’, ‘%s’)>» % (self.name, self.fullname, self.team)

Далее необходимо связать нашего посредника и нашу таблицу.  Для этого используется функция mapper. Синтаксис тут простой:

mapper(Character, heroes_table)

Соответственно, чтобы передать данные в БД, мы создаем экземпляр класса Character:

list= Character(«Tony», «Stark», «Avengers»)

Передаются эти данные через специальные сессии, с помощью которых мы будем подтверждать изменение базы данных — коммитить. Это делается через команду sessionmaker — это своего рода метакласс для сессий.

Session = sessionmaker(bind=engine) # связываем сессию и БД
session = Session() # создаем экземпляр класса Session
session.add(list) # добавляем данные в таблицу
session.commit() # подтверждаем транзакцию

Полный листинг:

[code]

engine = create_engine(‘sqlite:///:memory:’, echo=True)

metadata = MetaData()
heroes_table = Table(‘Marvel’, metadata,
Column(‘id’, Integer, primary_key=True),
Column(‘name’, String),
Column(‘fullname’, String),
Column(‘team’, String)
)

metadata.create_all(engine)

class Character:
def __init__(self, name, fullname, password):
self.name = name
self.fullname = fullname
self.team= team

def __repr__(self):
return «<Character(‘%s’,’%s’, ‘%s’)>» % (self.name, self.fullname, self.team)

mapper(Character, heroes_table) # Создание отображения
list= Character(«Tony», «Stark», «Avengers») # добавляем данные в базу

Session = sessionmaker(bind=engine)

session = Session()

session.add(list)
session.commit()

[/code]

Оцените автора
( Пока оценок нет )
Digital 2 - Цифровая реальность
Добавить комментарий