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