Django - resetowanie migracji

Django - resetowanie migracji
Photo by Brecht Corbeel / Unsplash

Podczas tworzenia aplikacji w Django często zdarza się że zmieniasz zdanie co to tego jak mają wyglądać poszczególne modele, lub w sposób naturalny aplikacja ewoluuje i struktury danych muszą zostać zmienione. W wyniku tego działania pojawia się spore zamieszanie w migracjach. Jeśli zerkniesz do folderu migrations to zauważysz, że framework utworzył wiele plików które często tworzą zupełnie niepotrzebne opreracje na bazie danych, np. tworzone jest dodatkowe pole w tabeli z domyślną wartością a w kolejnych migracjach jest usuwane, bądź zmieniana jest jego nazwa. Jeśli aplikacja jeszcze nie posiada środowiska produkcyjnego to możesz te migracje uprościć i uporządkować. Możesz zrobić to na dwa sposoby.

Sposób 1: usunięcie bazy danych

Jeśli projekt posiada w bazie danych tylko przykładowe wartości to w prosty sposób możemy uporządkować migracje: musisz usunąć bazę danych oraz pliki migracji.

Usuń pliki migracji

W pierwszej kolejności usuń wszystkie pliki z wyjątkiem __init__.py z folderu migrations znajdującego się w aplikacji.

Zwróć uwagę, że folder migrations znajduje się w folderze aplikacji (nie projektu). Jeśli masz kilka aplikacji w projekcie to w każdej z nich będzie folder migrations który należy opróżnić.

Wyczyść bazę danych

Następnie wyczyść bazę danych. Jeśli korzystasz z bazy sqlite to wystarczy że usuniesz plik db.sqlite3 który zwykle znajduje się w głównym folderze projektu.

Wykonaj nową migrację

Po usunięciu powyższych plików i wyczyszczeniu bazy danych utwórz migracje i je wykonaj poleceniami:

./manage.py makemigrations
./manage.py migrate
💡
Do uruchomienia poleceń Django używam składni która uruchamia plik manage.py w taki sam sposób jak zwykły skrypt w Linuxie - poleceniem "./manage.py". Możesz też uruchamiać go w inny sposób (wydaje mi się że jest on częściej używany w kursach i tutorialach) wywołując go jawnie z poleceniem python - "python manage". Obydwa sposoby dają taki sam efekt. Ja w tym artykule będę trzymał się pierwszej metody.

Nowe migracje są już gotowe.

Sposób 2: z zachowaniem bazy danych

Jeśli chcesz zachować istniejącą baza danych i uporządkować migracje możesz to zrobić czyszcząc historię migracji oraz usuwając pliki migracji.

Wyczyść historię migracji

Na początku wylistujemy sobie migracje poleceniem:

./manage.py showmigrations
Wynik polecenia ./manage.py showmigrations

Ja będę czyścił migracje dla aplikacji api. Aby usunąć migracje z historii wydaj polecenie:

./manage.py migrate --fake api zero
Wynik polecenia ./manage.py migrate --fake api zero
Pamiętaj żeby w poleceniu zamienić api na nazwę Twojej aplikacji.

Po wykonaniu polecenia usuwania migracji z historii wynik showmigrations powinien wyglądać tak:

Wynik polecenia ./manage.py showmigrations

Usuń pliki migracji

Po usunięciu historii musisz usunąć pliki. Usuwasz wszystkie pliki znajdujące się w katalogu migrations Twojej aplikacji za wyjątkiem pliku __init__.py.

Po usunięciu plików wynik polecenia showmigrations będzie wyglądał tak:

Wynik polecenia ./manage.py showmigrations

Jak widzisz aplikacja api nie posiada w tej chwili żadnych migracji.

Utwórz nową migrację

Teraz utwórz nową migrację poleceniem:

./manage.py makemigrations
Wynik polecenia ./manage.py makemigrations

Wykonaj symulację migracji

W tym wypadku nie możesz na nowo utworzyć bazy danych ponieważ ona istnieje. Musisz zasymulować utworzenie migracji tak, aby pojawiła się ona w historii ale nie wykonała operacji na samej bazie danych. Wykonasz to poleceniem:

./manage.py migrate --fake-initial
Wynik polecenia ./manage.py migrate --fake-initial

Gdy teraz wykonasz polecenie showmigrations otrzymasz widok podobny do tego:

Wynik polecenia ./manage.py showmigrations

W tym przypadku zastąpiłem tylko dwie migracje jedną migracją. W trakcie pisania aplikacji w Django często będziesz się spotykał z sytuacją gdy tych migracji będzie dużo. Wtedy warto zastosować powyższe polecenia i skrócić migracje do jednego skryptu.


👍 Dlaczego warto wykonać taki reset migracji?

  1. Dzięki jednemu skryptowi instalacja aplikacji na nowym serwerze będzie przebiegała szybciej.
  2. Unikasz sytuacji gdy jedna migracja tworzy nowe pole w bazie danych a kolejna je usuwa bądź zmienia jego nazwę.

👎 Jakie są minusy takiego rozwiązania?

  1. W historii migracji nie widzimy poszczególnych etapów dodawania modeli do bazy danych.
  2. Jeśli masz już aplikację na serwerze produkcyjnym to musisz zwrócić szczególną uwagę przy resetowaniu migracji aby nie uszkodzić produkcyjnej bazy danych.