Базы данных и Flask-SQLAlchemy: настройка

База данных хранит данные между запусками. ORM позволяет работать с ней через объекты Python, а не сырой SQL. Flask-SQLAlchemy связывает эту мощь с Flask.
ORM (объектно-реляционное отображение) превращает строки таблиц в объекты Python и наоборот. Ты пишешь user.name, а не SQL-запрос. Flask-SQLAlchemy 3.x даёт объект db, который сам настраивает движок и сессию под Flask.

Пока данные жили в памяти — они исчезали при перезапуске. Нужна постоянная память: база данных. Можно писать SQL руками, но это утомительно и опасно (инъекции, ручная сборка строк). ORM решает это: таблица становится классом, строка — объектом, столбец — атрибутом.

Flask-SQLAlchemy — официальная интеграция SQLAlchemy с Flask. В версии 3.x объект db создаётся на базе декларативного класса и подключается через фабрику:

# extensions.py
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
    pass

db = SQLAlchemy(model_class=Base)
# __init__.py (фабрика)
from .extensions import db

def create_app():
    app = Flask(__name__)
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///app.db"
    db.init_app(app)
    return app

Строка SQLALCHEMY_DATABASE_URI задаёт базу: sqlite:///app.db для разработки (файл на диске), postgresql://... для продакшена. SQLite не требует сервера — идеален для учёбы. db.init_app привязывает расширение к приложению (помнишь паттерн из урока про фабрику).

ORM избавляет не только от рутины написания SQL, но и от целого класса уязвимостей: при работе через объекты и параметризованные запросы SQL-инъекции практически исключены, тогда как ручная склейка строк запроса — классический источник взломов. Flask-SQLAlchemy 3.x берёт на себя настройку движка и сессии под жизненный цикл Flask, поэтому тебе не нужно вручную управлять соединениями. Выбор базы стоит делать осознанно: SQLite — файл без отдельного сервера, идеален для учёбы, прототипов и тестов; PostgreSQL — надёжная серверная СУБД для продакшена с конкурентным доступом. Строку подключения, как и секреты, держат в переменных окружения, чтобы разработка и продакшен использовали разные базы без правки кода.

Как работает под капотом

db управляет двумя вещами: движком (engine) — пулом соединений с базой — и сессией (session) — «рабочим столом», где копятся изменения до commit. ORM транслирует операции с объектами в SQL и обратно.

  Python-объект User      ORM-слой           База данных
  ──────────────────      ────────           ───────────
  user.name = "Анна"  ──▶ db.session     ──▶ UPDATE users
  db.session.commit() ──▶ собрать SQL    ──▶ SET name='Анна'
                          выполнить через engine (пул)
  User(...)           ◀── собрать объект ◀── SELECT * FROM users

Смоделируем суть ORM: объект Python ↔ строка-словарь «таблицы».

table = []   # имитация таблицы users

class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

def save(obj):                       # как db.session.add + commit
    row = {"id": len(table) + 1, "name": obj.name, "email": obj.email}
    table.append(row)
    return row["id"]

def all_users():                     # как select(User)
    return [User(r["name"], r["email"]) for r in table]

save(User("Анна", "[email protected]"))
save(User("Боб", "[email protected]"))
for u in all_users():
    print(u.name, u.email)

Запусти: объекты сохраняются как строки и читаются обратно объектами. Настоящий SQLAlchemy делает то же, но с реальной базой, типами столбцов и SQL под капотом.

Частые ошибки

  • Создавать db внутри фабрики. Тогда модели не смогут его импортировать. Создавай в extensions.py, привязывай через init_app.
  • Забыть SQLALCHEMY_DATABASE_URI. Без строки подключения база неизвестна.
  • Тащить продакшен на SQLite под нагрузкой. SQLite хорош для учёбы; для боевого многопользовательского сервиса — PostgreSQL.

Best practices

  • db — глобально в extensions.py, init_app — в фабрике.
  • Строку подключения бери из переменной окружения, не хардкодь.
  • SQLite для разработки/тестов, PostgreSQL для продакшена.

Что запомнить

  • ORM отображает таблицы на классы, строки на объекты Python.
  • Flask-SQLAlchemy 3.x даёт объект db с движком и сессией.
  • db создают в extensions.py пустым, привязывают через init_app в фабрике.
  • SQLite — для разработки, PostgreSQL — для продакшена; URI из окружения.

Итог: ORM связывает объекты Python и таблицы, Flask-SQLAlchemy 3.x даёт объект db с движком и сессией, подключаемый через init_app. Дальше — описание моделей-таблиц.

Проверьте себя
1. Что делает ORM вроде SQLAlchemy?
AУскоряет HTTP-запросы
BСвязывает строки таблиц с объектами Python, избавляя от ручного SQL
CШифрует базу данных
DЗаменяет Jinja2
2. Почему db создают в extensions.py, а не внутри create_app?
AТак быстрее
BЧтобы модели и другие модули могли импортировать db; привязка идёт через init_app
CЭто требование SQLite
DИначе db зашифруется