Работа с базами данных – необходимая составляющая любого серьезного интернет-проекта, будь то интернет-магазина, социальной сети, лендинга или другого сайта, где приходится обрабатывать большие массивы информации. Поэтому надо знать, как правильно работать с ними.
Типы баз данных
На данный момент есть две системы баз данных, которые конкурируют друг с другом:
- Реляционные базы данных.
- Нереляционные базы или NoSQL.
Первые в веб-приложениях используются очень активно. Причем даже гигантами интернета, такими как Facebook. Их преимущества – удобство и функциональность.
Особенность реляционных баз данных в том, что они хранят сведения в таблицах, а для связи между несколькими из них, используются внешние ключи. Такими базами данных также поддерживаются транзакции. Это означает, что возможно исполнение набора SQL-операторов, которые должны быть атомарными (atomic). Под ними подразумеваются те, при исполнении которых выполняется принцип «все или ничего».
В последние годы базы данных второго типа начали значительно набирать популярность. Их особенность в том, что сведения содержатся не в таблицах, а в них есть отдельные структуры, которые осуществляют хранение определенной информации. Их преимущество – высокая скорость работы. При этом транзакции не поддерживаются.
Реляционные базы данных гораздо старше. Поэтому многие разработчики им доверяют. Поэтому далее мы будем рассматривать именно базы данных этого типа, поскольку они много где используются, а в освоении они проще.
SQLAlchemy и Flask-SQLAlchemy
SQLAlchemy – это фреймворк, предназначенный для работы с реляционными базами данных в Python. Он был создан давно – в 2005 году Майком Байером. Он поддерживает базы данных разных типов – MySQL, PostgreSQL, Oracle, MS-SQL, SQLite и другие.
В SQLAlchemy встроена поддержка мощной технологии объектно-реляционного отображения, дающей возможность использовать объектно-ориентированное программирование для взаимодействия с базами данных. Это значительно удобнее, чем язык структурированных запросов. Правда, если понадобятся возможности SQL, разработчик всегда может их использовать.
Flask-SQLAlchemy – это расширение для Flask, который позволяет использовать этот фреймворк в рамках Flask. Также он несколько упрощает работу с ним. Чтобы установить Flask-SQLAlchemy, необходимо воспользоваться такой командой.
(env) gvido@vm:~/flask_app$ pip install flask-sqlalchemy
Устанавливается как сам пакет, так и дополнительные модули. Чтобы начать его использовать, необходимо выполнить импорт класса SQLAlchemy из пакета flask_sqlalchemy и создать элемент класса SQLAlchemy, передав экземпляр программы.
Давайте внесем некоторые коррективы в код main2.py.
#... from forms import ContactForm from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'a really really really really long secret key' manager = Manager(app) db = SQLAlchemy(app) class Faker(Command): #...
Чтобы получить доступ к функциям SQLAlchemy, мы воспользовались экземпляром db объекта SQLAlchemy.
Далее необходимо сообщить, в каком месте находится база данных в виде URI. Формат такой:
dialect+driver://username:password@host:port/database
Для ссылки на название базы данных используется dialect. Имя может быть таким, как mysql, mssql, postgresql, и так далее.
А для того, чтобы сослаться на DBAPI, используется driver. Он применяется для налаживания соединения с базой данных. Изначально SQLAlchemy не нуждается в дополнительных драйверах, чтобы работать с SQLite. Для взаимодействия с другими базами данных, необходимо инсталлировать конкретный драйвер, который имеет хорошую совместимость с DBAPI.
Что такое DBAPI?
Здесь может появиться вопрос: а что вообще такое DBAPI? Это стандарт, который определяет API для доступа к базам данных от различных производителей.
Приведем таблицу, содержащую ряд баз данных и драйверов для них, совместимых с DBAPI:
База данных | Драйвер DBAPI |
MySQL | PyMysql |
PostgreSQL | Psycopg 2 |
MS-SQL | pyodbc |
Oracle | cx_Oracle |
Указание имени пользователя и пароля осуществляется лишь если в этом есть необходимость. Если они введены, то используются для авторизации в базе данных.
host – расположение сервера базы данных.
port – порт сервера базы данных.
database – имя базы данных.
Давайте приведем примеры некоторых URL баз данных, которые могут использоваться для наиболее популярных типов.
# URL базы данных для MySQL с использованием драйвера PyMysql 'mysql+pymysql://root:pass@localhost/my_db' # URL базы данных для PostgreSQL с использованием psycopg2 'postgresql+psycopg2://root:pass@localhost/my_db' # URL базы данных для MS-SQL с использованием драйвера pyodbc 'mssql+pyodbc://root:pass@localhost/my_db' # URL базы данных для Oracle с использованием драйвера cx_Oracle 'oracle+cx_oracle://root:pass@localhost/my_db'
Обратите внимание на то, что формат URL базы данных для SQLite немного отличается, поскольку эта база данных использует файл, и для получения доступа к ней не требуется имени пользователя и пароля.
# Для Unix / Mac мы используем 4 слеша sqlite:////absolute/path/to/my_db.db # Для Windows мы используем 3 слеша sqlite:///c:/absolute/path/to/mysql.db
Flask-SQLAlchemy в своей работе использует ключ конфигурации SQLALCHEMY_DATABASE_URI для определения URI базы данных. Давайте внесем соответствующие изменения в наш файл.
#... app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'a really really really really long secret key' app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:pass@localhost/flask_app_db' manager = Manager(app) db = SQLAlchemy(app) #...
Мы будем использовать базу MySQL, поэтому необходимо удостовериться в том, что она установлена на компьютере.
Как создавать модели?
Таблица базы данных в Python имеет отдельный класс, который называется моделью. Ее атрибуты такие же, как и столбцы таблицы, которой она соответствует. Класс модели наследуется из db.Model и обозначает колонки, как экземпляры класса db.Column. Давайте внесем соответствующие коррективы в main2.py.
#... from flask_sqlalchemy import SQLAlchemy from datetime import datetime #... class Post(db.Model): __tablename__ = 'posts' id = db.Column(db.Integer(), primary_key=True) title = db.Column(db.String(255), nullable=False) slug = db.Column(db.String(255), nullable=False) content = db.Column(db.Text(), nullable=False) created_on = db.Column(db.DateTime(), default=datetime.utcnow) updated_on = db.Column(db.DateTime(), default=datetime.utcnow, onupdate=datetime.utcnow) def __repr__(self): return "<{}:{}>".format(self.id, self.title[:10])
В этом примере мы используем 5 переменных класса для создания модели Post, почти каждая из которых является экземпляром класса. Единственное исключение – __tablename__, которая нужна для обозначения имени таблицы базы данных.
По умолчанию, название таблицы является названием модели. Если необходимо указать точное название таблицы, необходимо использовать эту переменную.
Конструктор db.Column содержит два аргумента. Первый из них – это тип создаваемого столбца. Таких много, причем разработчик всегда может создать собственные. Приведем таблицу с описанием типов колонок и соответствующим типам Pyhton и SQL.
SQLAlchemy | Python | SQL |
BigInteger | int | BIGINT |
Boolean | bool | BOOLEAN или SMALLINT |
Date | datetime.date | DATE |
DateTime | datetime.date | DATETIME |
Integer | int | INTEGER |
Float | float | FLOAT или REAL |
Numeric | decimal.Decimal | NUMERIC |
Text | str | TEXT |
Также пользователь может задать дополнительные ограничения для колонки, передав их в качестве аргументов-ключевых слов конструктору db.Column.
Определение отношений (связей)
Ранее мы создали модель Post, содержащую несколько полей. На деле же, возможно отдельное существование классов моделей. Подавляющее число времени они взаимосвязаны с другими моделями отношениями разного типа: один к одному, один ко многим, и многие ко многим.
Необходимо дальше поработать над аналогией блога. Как правило, пост в блоге принадлежит к одной категории, и в нем содержится один или несколько тегов. Проще говоря, установлено отношение один-к-одному между постом и категорией и отношение многие-ко-многим между постом и тегом.
Давайте изменим main2.py таким образом, чтобы добавить Category и Tag.
#... def updating_session(): #... return res class Category(db.Model): __tablename__ = 'categories' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(255), nullable=False) slug = db.Column(db.String(255), nullable=False) created_on = db.Column(db.DateTime(), default=datetime.utcnow) def __repr__(self): return "<{}:{}>".format(id, self.name) class Posts(db.Model): # ... class Tag(db.Model): __tablename__ = 'tags' id = db.Column(db.Integer(), primary_key=True) name = db.Column(db.String(255), nullable=False) slug = db.Column(db.String(255), nullable=False) created_on = db.Column(db.DateTime(), default=datetime.utcnow) def __repr__(self): return "<{}:{}>".format(id, self.name) #...
Выводы
Конечно, работа с базами данных требует гораздо более широкого подхода. Тем не менее, если понимать эти основы, уже можно взаимодействовать с информацией веб-приложения. А далее уже создать интернет-магазин или собственную социальную сеть. Flask имеет гибкий функционал для этого.