Ссылки на внешние переменные в миграциях данных Django

Для моделей мы используем apps.get_model(), чтобы убедиться, что при миграции будет использоваться правильная версия модели (та, которая была на момент определения миграции). Но как быть с "обычными" переменными (не моделями), импортированными из базы данных?

Предположим, я хочу просто изменить значение поля с помощью переменной, которую я определил где-то в кодовой базе. Например, я хочу превратить всех обычных пользователей в администраторов. Я сохранил роли пользователей в перечислении (UserRoles). Один из способов написать миграцию будет таким:

from django.db import migrations
from user_roles import UserRoles


def change_user_role(apps, schema_editor):
    User = apps.get_model('users', 'User')
    users = User.objects.filter(role=UserRoles.NORMAL_USER.value)
    for user in users:
        user.role = UserRoles.ADMIN.value

    User.objects.bulk_update(users, ["role"])


def revert_user_role_changes(apps, schema_editor):
    User = apps.get_model('users', 'User')
    users = User.objects.filter(role=UserRoles.ADMIN.value)
    for user in users:
        user.role = UserRoles.NORMAL_USER.value

    User.objects.bulk_update(users, ["role"])


class Migration(migrations.Migration):

    dependencies = [
        ('users', '0015_auto_20220612_0824'),
    ]

    operations = [
        migrations.RunPython(change_user_role, revert_user_role_changes)
    ]

Но теперь есть проблемы.

  1. Если когда-нибудь в будущем я удалю переменную UserRoles (потому что изменю реализацию), это нарушит миграции. Поэтому я не смогу повторно запустить миграции локально, чтобы создать базу данных с нуля.
  2. Если я модифицирую переменную (например, изменю порядок значений перечисления), это приведет к неожиданным последствиям при выполнении обратной операции над существующей базой данных.

Я использовал пример с перечислением, но это можно применить к любой переменной, на которую ссылаются внутри миграций.

Какая лучшая практика для миграций? Должны ли мы всегда жестко кодировать значения, не обращаясь к внешним переменным, которые могут измениться?

Вернуться на верх