Как переименовать приложение в Django
Как-то в бекенде школы меня перестало устраивать название приложения в Django. Когда я начинал проект, у нас можно было купить только курсы, и приложение с ними называлось courses. Потом к курсам добавились записи (record) и наборы (bundles). Конечно мне захотелось переименовать приложение courses в products, чтобы уменьшить когнитивную нагрузку при чтении кода.
К сожалению, я не нашёл ни одного решения, кроме стрёмного django-rename-app, который предлагал мне выполнять management-команды в консольке на проде. Кроме того, что это ломает любые пайплайны CI\CD, там ещё и код был не очень понятный. Так что в итоге я решил сделать это сам. Оказалось сложно, поэтому я написал эту инструкцию.
Исходные условия:
- CI\CD пайплайн, который запускает миграции при каждом деплое.
- Данные терять нельзя.
- Мы не стесняемся править старые миграции.
Все изменения я делал на живом проекте, так что примеры будем брать прямо из пулл-реквестов.
- Подменяем имя приложения в истории миграций:
./manage.py makemigrations <some-other-app> -n RenameOldApp --empty
. Коммит. - Деплоим миграцию на прод. После этого шага ничего нельзя деплоить до конца.
- Делаем новый пулл-реквест.
- Переименовываем папку с приложением:
git mv courses products
- Заменяем все упоминания старого приложения в миграциях. Коммит.
- У всех моделей в новом приложения в Meta прописываем
db_table
с именем старого приложения. В моём случае, если модель называется bundle и лежала в приложении courses, нужно прописатьdb_table = 'courses_bundle'
. Коммит. - В старых миграциях, которые используют операцию
CreateTable
, добавляем новуюdb_table
вoptions
. Коммит. - Меняем упоминания приложения в коде, можно автозаменой. Коммит.
- Проверяем,
./manage.py makemigrations --check
. Новых автоматических миграцией был не должно, ошибок тоже. - Деплоим на прод.
В итоге у нас получается два деплоя: первый подменяет миграции, а второй — код. В результате модели будут лежать по новому адресу, но ходить в старые таблицы. Для меня это было плюсом, т.к. не пришлось переделывать аналитические SQL-запросы, которые ходят в базу из Metabase.