Работа с базой данных через SQLAlchemy

Подключение к базе данных и создание таблиц

Последнее обновление: 15.04.2024

FastAPI поддерживает работу с самыми разными системами баз данных: PostgreSQL, MySQL, SQLite, Oracle, Microsoft SQL Server и т.д. Причем мы не ограничены только реалиционными базами данных и равным образом использовать и нереляционные, так называемые NoSQL-системы баз данных.

При работе с базами данных самым простым решением является использование специальных инструментов - ORM (Object Relational Mapper), которые позволяют абстрагироваться от строения базы данных в конкретной СУБД и позволяет автоматически связать сущности в коде Python с таблицами в базе данных. В FastAPI наиболее распространным ORM-инструментом является SQLAlchemy ORM

Рассмотрим работу с базой данных через SQLAlchemy ORM на примере SQLite, поскольку SQLite не требует установки сервера или каких-то дополнительных инструментов. Кроме того, перейти от одной СУБД к другой не составить особого труда и почти не потребует изменения кода взаимодействия с БД, за исключением пары строк кода.

Прежде всего нам надо установить сам SQLAlchemy с помощью команды

pip install sqlalchemy

Определение строки подключения к БД

Прежде всего для подключения к базе данных необходима строка подключения, которая включает адрес базы данных и другие различные параметры, необходимые для подключения. Для разных СУБД строка подключения может отличаться. Пример строки подключения к SQLite:

# строка подключения
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"

Для sqlite строка подключения начинается с sqlite://, затем идет относительный или абсолютный путь к файлу:

 sqlite:///относительный_путь/file.db
 sqlite:////абсолютный_путь/file.db

В данном случае это "./sql_app.db", который указывает, что файл базы данных будет называться "sql_app.db" и будет располагаться в текущей папке.

В зависимости от конкретной субд строка подключения будет различаться. Так, если бы мы подключись бы к базе данных PostgreSQL, то строка подключения имела бы следующий формат:

SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"

где user - имя пользователя на сервере PostgreSQL, password - пароль, postgresserver - адрес сервера, а db - имя базы данных на сервере.

При подключении к другим системам баз данных по сути это единственная строка кода, которая потребует изменения.

Определение движка

После определения строки подключения создается движок SQLAlchemy с помощью функции create_engine():

from sqlalchemy import create_engine

SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"

# создание движка
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)

Первый параметр функции указывает на строку подключения - то есть по сути базу данных, к которой идет подключение.

Второй параметр - дополнительные параметры подключения в виде словаря connect_args. В частности, элемент "check_same_thread": False предназначен только для SQLite и указывает, что для взаимодействия с базой данных SQLite в рамках одного запроса может использоваться больше одного потока. Зачем это надо? По умолчанию SQLite разрешает взаимодействовать с БД только одному потоку, чтобы один поток обрабатывал отдельный запрос, что позволяет предотвратить использование одного потока для разных запросов. Но в FastAPI в рамках одного и того же запроса с базой данных могут взаимодействовать более одного потока. Собственно поэтому необходима подобная настройка для получения необходимых разрешений. При этом каждый запрос будет получать свой собственный сеанс подключения к базе данных через механизм внедрения зависимостей, поэтому в механизме по умолчанию нет необходимости.

При работе с другими СУБД достаточно указать только адрес подключения:

engine = create_engine(SQLALCHEMY_DATABASE_URL)

Определение моделей

Модели представляют классы, которые соответствуют определению таблиц в базе данных и объекты которых хранятся в этих таблицах. И одним из преимуществ SQLAlchemy является то, что мы можем работать таблицами через эти модели-классы языка Python, не прибегая к созданию запросов на языке SQL.

Для создания моделей необходима базовая модель, от которой потом наследуются остальные модели. Для создания базовой модели можно использовать различные способы, но самый короткий - создания класса модели с помощью функции declarative_base():

from sqlalchemy.orm import DeclarativeBase
 
class Base(DeclarativeBase): pass

То есть в данном случае определяется класс Base - базовая модель. Затем уже можно определить конкретные модели, данные которых будут храниться в БД. Например:

from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import  Column, Integer, String

class Base(DeclarativeBase): pass

class Person(Base):
    __tablename__ = "people"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String)
    age = Column(Integer,)

Здесь определена модель Person, которая представляет пользователя. Она наследуется от Base и определяет ряд атрибутов.

Атрибут __tablename__ хранит имя таблицы, с которой будет сопоставляться текущая модель. То есть данные класса Person будут храниться в таблице "people".

Для хранения данных в классе модели определяются атрибуты, которые сопоставляются со столбцами таблицы. Такие атрибуты в качестве значения получаются объект Column. В данном случае класс Person определяет три таких атрибута: id, name и age, для которых в таблице people будут создаваться одноименные столбцы.

Класс Column с помощью параметров конструктора определяет настройки столбца в таблицы. Здесь в конструктор вначале передается тип столбца. Так, у id и age тип столбца - Integer, то есть целое число. А столбец name представляет тип String, то есть строку.

Кроме того, в конструктор можно передать ряд дополнительных параметров. Так, для столбца id передаются параметры primary_key и index. Значение primary_key=True указывает, что данный столбец будет представлять первичный ключ. А параметр index=True говорит, что для данного столбца будет создаваться индекс.

Создание базы данных и таблиц

Для создания базы данных и таблиц по метаданным моделей применяется метод Base.metadata.create_all(). Его ключевой параметр - bind принимает класс, который используется для подключения к базе данных. В качестве такого класса применяется созданный ранее движок SQLAlchemy. Если база данных и все необходимые таблицы уже имеются, то метод не создает заново таблицы.

Посмотрим на простейшем примере. Все объединим и определим в файле приложения следующий код:

from sqlalchemy import create_engine
from sqlalchemy.orm import DeclarativeBase
from sqlalchemy import  Column, Integer, String

from fastapi import FastAPI

# строка подключения
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"

# создаем движок SqlAlchemy
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
#создаем базовый класс для моделей
class Base(DeclarativeBase): pass

# создаем модель, объекты которой будут храниться в бд
class Person(Base):
    __tablename__ = "people"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String)
    age = Column(Integer,)

# создаем таблицы
Base.metadata.create_all(bind=engine)

# приложение, которое ничего не делает
app = FastAPI()

После запуска приложения в папке проекта будет создана таблица sql_app.db:

Подключение к базе данных Sqlite и создание таблиц через SqlAlchemy в FastAPI и Python

Мы можем открыть эту базу данных с помощью любой программы для просмотра баз данных sqlite (например, с помощью DB Browser for SQLite) и увидеть содержимое бд:

Подключение к базе данных Sqlite и создание таблиц через SqlAlchemy в FastAPI
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850