Dodanie unikalnej kolumny do istniejącej tabeli w Django

Czasami zachodzi potrzeba dodania nowej, unikalnej kolumny do istniejącego już modelu w Django. Niestety jeśli w tabelce istnieją już wpisy, otrzymamy błąd. W takim przypadku, dodanie nowej kolumny należy podzielić na 3 kroki. Stworzenie kolumny bez indeksu unikalnego, wygenerowanie unikalnych wartości, dodanie indeksu. Możemy to osiągnąć, za pomocą standardowego mechanizmu migracji, który znajduje się w Django. Zacznijmy od przykładowego kodu:

from __future__ import unicode_literals
import common.functions
from django.db import migrations, models
def uniquify_keys_for_events(apps, schema_editor):
events = apps.get_model("event", "Event").objects.all()
for event in events:
event.key = common.functions.generate_random_string_32()
event.save()
class Migration(migrations.Migration):
dependencies = [
('event', '0002_auto_20170102_1816'),
]
operations = [
migrations.AddField( # krok 1
model_name='event',
name='key',
field=models.CharField(max_length=32, null=True),
),
migrations.RunPython(uniquify_keys_for_events), # krok 2
migrations.AlterField( # krok 3
model_name='event',
name='key',
field=models.CharField(max_length=32, default=common.functions.generate_random_string_32, unique=True))
]
view raw migration.py hosted with ❤ by GitHub

W przykładzie do modelu Event dodajemy kolumnę key, która zawiera unikalny ciąg znaków. Pierwszy krok tworzy nową kolumnę. W kroku 2 przekazujemy do mechanizmu funkcje Pythona. Jako parametry otrzyma ona obiekty, za pomocą których będzie mogła wykonywać operacje na bazie danych. W przykładowej funkcji wyciągamy wszystkie wiersze, które znajdują się w bazie. Przechodzimy pojedynczo przez każdy element, generujemy losowy ciąg znaków i zapisujemy zmiany w bazie. Można przyjąć dowolną strategię generowania unikalnej wartości, dla liczb może to być po prostu kolejny numer. Gdy już mamy unikalne wartości w każdym wierszu tabelki, możemy na nią nałożyć indeks unikalny (krok 3).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *