Якщо ви не були з нами на попередніх заняттях, то, мабуть, перебуваєте в щасливому невіданні щодо того, що моделі даних і сама база даних не завжди синхронізуються "автоматично". А ті, хто вже був тут, точно знають: міграції — це ваш рятувальний круг, який допомагає зручно керувати змінами і уникати хаосу в базі даних.
Почнемо з того, як можна змінити структуру бази даних через модифікацію ваших моделей даних. Завдання максимально просте: ми хочемо, щоб зміни в коді наших моделей синхронізувалися з базою даних через Alembic.
Приклад задачі
Припустимо, у нас є така модель даних:
# models.py
from sqlalchemy import Column, Integer, String
from database import Base
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
Ми вирішили, що хочемо додати нове поле email, щоб зберігати поштові адреси користувачів. Для цього просто змінимо нашу модель:
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
name = Column(String, index=True)
email = Column(String, unique=True, nullable=False)
Зверніть увагу, що ми додали нові обмеження:
unique=True: щоб кожен email був унікальним.nullable=False: поле обов'язкове для заповнення.
Тепер залишається синхронізувати ці зміни з базою даних через Alembic.
Генерація міграції для змін
Щоб Alembic "зрозумів", що ми змінили в моделі, і згенерував міграцію, використаємо команду:
alembic revision --autogenerate -m "Додано поле email у таблицю users"
Давайте розберемося, що тут відбувається:
revision: створює нову ревізію міграції.--autogenerate: дозволяє Alembic автоматично згенерувати зміни на основі оновлених моделей.-m: додає коментар або опис ревізії (дуже корисно для історії міграцій).
Після виконання команди Alembic згенерує новий файл міграції, який буде виглядати приблизно так:
"""Додано поле email у таблицю users"""
from alembic import op
import sqlalchemy as sa
# ID ревізії та батьківської ревізії
revision = 'abcdef123456'
down_revision = '123456abcdef'
branch_labels = None
depends_on = None
def upgrade():
# Додавання нового стовпця
op.add_column('users', sa.Column('email', sa.String(), nullable=False))
op.create_unique_constraint('uq_users_email', 'users', ['email'])
def downgrade():
# Видалення стовпця (відкат змін)
op.drop_constraint('uq_users_email', 'users', type_='unique')
op.drop_column('users', 'email')
Застосування міграції
Тепер, коли міграція готова, її треба застосувати до бази даних. Для цього запускаємо команду:
alembic upgrade head
Ця команда застосовує всі міграції, починаючи з останньої зафіксованої версії (якщо є нові). Після виконання можна перевірити структуру таблиць у базі даних, і ви побачите, що стовпець email додано. Ура, успіх!
Перевірка змін у базі даних
Щоб переконатися, що все працює правильно, можна скористатися будь-яким інструментом для роботи з базами даних. Наприклад, у PostgreSQL можна виконати:
\d users
І ви побачите, що стовпець email додано. Крім того, обмеження UNIQUE і NOT NULL також будуть вказані.
Відкат міграцій
Бувають ситуації, коли потрібно скасувати зміни (наприклад, у продакшені стався "нервний зрив"). Для цього потрібно використати команду:
alembic downgrade -1
Ця команда відкотить останню виконану міграцію. Якщо ви хочете повернутися до конкретної версії, можна вказати її ID ревізії:
alembic downgrade 123456abcdef
Після відкату змін стовпець email буде видалений, і база даних повернеться до попереднього стану.
Типові помилки та підводні камені
- Помилка: "Target database is not up to date".
Це може статися, якщо ви забули застосувати міграції до внесення нових змін. Спробуйте виконатиalembic upgrade headперед створенням нової міграції. - Конфлікти між міграціями.
Якщо кілька розробників паралельно працюють над міграціями, легко стикнутися з конфліктами. Щоб уникнути цього, синхронізуйте свої зміни через Git і проводьте обговорення в команді. - Ручне редагування міграцій.
Інколи Alembic може не розпізнати складні зміни автоматично (наприклад, зміну типу стовпця). В такому випадку доведеться вручну редагувати файл міграції. Це нормально — просто будьте уважні.
Приклад використання в реальному проєкті
Уявіть, що ви працюєте над великим проєктом e-commerce. Там бази даних змінюються постійно: додаються нові моделі, модифікуються існуючі. Міграції допомагають вам підтримувати синхронність між моделями і базою даних, навіть якщо над проєктом працює кілька команд.
Крім того, відкат міграцій врятує вас у разі потреби швидкого відновлення, якщо щось піде не так. Наприклад, ви додали колонку і швидко зрозуміли, що вона не потрібна (або гірше: зламала продакшен). З Alembic відкат змін — це кілька секунд, а не години роботи.
Тепер ви впевнено можете змінювати структуру бази даних через Alembic, і це стане вашим незамінним інструментом у подальшій роботі. На наступних лекціях ми заглибимося в керування версіями і інтеграцію Alembic у складніші проєкти.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ