Migracje w Django za pomocą South
South to narzędzie do migracji struktury i danych zawartych w bazie danych dla aplikacji Django. South w praktycznie całkowicie zautomatyzowany sposób potrafi śledzić zmiany w modelach i tworzyć nowe migracje aktualizujące strukturę tabel w bazie danych. Ułatwia to rozwój aplikacji (nie trzeba tworzyć migracji ręcznie), jak i jej utrzymanie, zarządzanie (można cofnąć się do wybranej starszej migracji reprezentującej np. starszą wersję aplikacji).
Instalacja i konfiguracja South
Najprościej zainstalować South za pomocą pip:Podstawy migracji
Tworząc nową aplikacje zamiast tworzyć tabele modeli za pomocą syncdb zaczynamy używać migracji south. By stworzyć pierwszą migrację wystarczy wykonać:from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=100)
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
Zamiast "--initial" stosujemy "--auto", po czym wykonujemy stworzoną migrację. W tym prostym przykładzie stworzenie migracji będzie całkowicie automatyczne.
A gdyby w zmianie było pole, które nie może być puste?:
class MyModel(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
number = models.IntegerField()
? The field 'MyModel.number' does not have a default specified, yet is NOT NULL. ? Since you are adding this field, you MUST specify a default ? value to use for existing rows. Would you like to: ? 1. Quit now, and add a default to the field in models.py ? 2. Specify a one-off value to use for existing columns now
Możemy wybrać opcję 1 co przerwie proces tworzenia migracji. Możemy wtedy zmienić coś w modelu, np. nadawać wartość wartość domyślną. Możemy także wybierając opcję 2 podać domyślną wartość na potrzeby migracji (tylko dla istniejących rekordów).
Migracje danych
Gdybyśmy chcieli dodać takie pole do istniejącego modelu z rekordami:slug = models.SlugField(unique=True)
slug = models.SlugField(unique=True, null=True)
Następnie migrujemy dane - generujemy unikalne wartości dla kolumny. Na koniec usuwamy null dla kolumny kolejną migracją.
By wygenerować pustą migrację danych wykonujemy polecenie:# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
class Migration(DataMigration):
def forwards(self, orm):
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
def backwards(self, orm):
"Write your backwards methods here."
Metoda forward dotyczy migracji jaką chcemy przeprowadzić. backwards dotyczy operacji wstecznej - gdybyśmy później chcieli cofnąć migrację (jeżeli zmiana jest "poważna" i nie ma możliwości jej cofnięcia to można wyłączyć opcję wstecznej migracji).
W tej migracji musimy ustawić unikalne wartości dla pola slug. Naprościej można zrobić to tak: def forwards(self, orm):
# Note: Remember to use orm['appname.ModelName'] rather than "from appname.models..."
for i in orm['first_app.MyModel'].objects.all():
i.slug = i.id
i.save()
Migracje wsteczne
Jeżeli chcemy cofnąć stan tabel do konkretnej migracji wystarczy wykonać:Zależności między migracjami
Migracje zawierające relacje mogą przy budowaniu struktury od zera wykonać się w niewłaściwej kolejności (migracja z relacją będzie chciała się wykonać przed migracją tworzącą tabelę wykorzystywaną w tej relacji). Problem ten może pojawić się w systemach testów, czy budowania aplikacji, gdzie migracje są wykonywane od zera.
Rozwiązanie jest proste. Wystarczy do klasy stworzonej migracji dodać atrybut "depends_on":depends_on = (
("NAZWA_APLIKACJI", "NAZWA_MIGRACJI"),
)
Comment article