Слушал «сначала makemigrations, потом migrate» и делал на автопилоте, пока однажды не изменил модель и не понял, почему база «не видит» поле. Раздражение уперлось в вопрос: а что вообще происходит по шагам?
Нейтрально: модель описывает «что хочу», makemigrations создаёт файл-изменение схемы (базу не трогает), migrate применяет его к реальной БД. Пропуск первого — путаница «в коде есть, а в базе нет».
python manage.py makemigrations # создаёт 0001_xxx.py в migrations
python manage.py migrate # применяет не применённые
python manage.py showmigrations # наглядно: отмечено / не отмечено
Теперь у меня рефлекс: в CI стоит makemigrations --check — если модель изменилась без миграции, сборка падает громко. День начался с досады на себя, а закончился пониманием миграций как «истории схемы». Долго, зато въелось намертво.