Как Django определяет порядок применения миграций?

«Как Django определяет порядок применения миграций?» — вопрос из категории Django, который задают на 10% собеседований Python Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Django определяет порядок применения миграций путем построения графа зависимостей (dependency graph). Этот механизм гарантирует, что изменения в базе данных применяются в правильной последовательности, даже при работе с несколькими приложениями.

Ключевой элемент — атрибут dependencies

Каждый файл миграции, сгенерированный командой python manage.py makemigrations, содержит класс Migration с атрибутом dependencies. В этом списке указываются миграции, которые должны быть применены до текущей.

Пример файла миграции 0002_add_author_bio.py:

# myapp/migrations/0002_add_author_bio.py
from django.db import migrations, models

class Migration(migrations.Migration):

    # Эта миграция зависит от самой первой миграции в этом же приложении
    dependencies = [
        ('myapp', '0001_initial'),
    ]

    operations = [
        migrations.AddField(
            model_name='author',
            name='bio',
            field=models.TextField(default=''),
        ),
    ]

Как это работает:

  1. Генерация: При создании новой миграции Django автоматически определяет, от каких предыдущих миграций она зависит (обычно от последней в том же приложении), и записывает это в dependencies.
  2. Выполнение: Команда python manage.py migrate сначала строит полный граф всех миграций во всех приложениях проекта. Затем она проходит по этому графу в топологическом порядке, применяя сначала те миграции, у которых нет неудовлетворенных зависимостей.

Важные моменты:

  • Имена файлов: Номера в именах файлов (0001_, 0002_) служат для удобства разработчиков и помогают избежать конфликтов имен, но не являются основным механизмом определения порядка. Главное — это dependencies.
  • Межприложенные зависимости: Если модель в одном приложении (app_b) имеет ForeignKey на модель в другом (app_a), Django автоматически создаст зависимость миграции app_b от миграции app_a.
  • Конфликты: Если два разработчика одновременно создают миграции в одной ветке, может возникнуть конфликт. Django обнаружит это и предложит объединить их с помощью команды python manage.py makemigrations --merge.