Django data migrationlar

Django migrationlar Django’nun beni kendine hayran bırakan özelliklerinden biri olduğunu çok rahat söyleyebilirim. Bir satır bile SQL yazmadan database tablolarında değişikliklik yapabiliyorum. Henüz DB migrationlarını Django kadar zahmetsiz ve temiz yöneten herhangi bir dille yazılmış bir framework göremedim. Cansın Django :)

Bazı zamanlar oluyorki modellerde yaptığımız değişikliklerden ötürü bir migration oluşturduğumuzda bu migrationa yeni eklemeler yapmamız veyada bu migrationdan ötürü eski data üzerinde işlemler yapmamız gerekebiliyor.

Şimdi örnek bir senaryo üzerinden custom migration nasıl yazılır ondan bahsetmeye çalışacağım.

Şuan üzerinde çalıştığım projeyi ilk geliştirmeye başladığımızda ilk olarak gelir-gider takibi gibi olmazsa olmaz özellikleri geliştirdik. Daha sonra muhasebe modülünü geliştirdik. Muhasebe modülünü de geliştirdiğimizde artık bir gelir ve gider oluştuğunda otomatik olarak muhasebe fişi de oluşuyordu. Fakat muhasebe modülü geliştirilmeden önce oluşmuş olan gelir ve giderler için muhasebe fişi oluşturmamız gerekiyordu. Bunun için bir custom migration yazdık ve bu migrationla daha önceden oluşmuş olan bütün gelir giderler için fişlerini oluşturduk.

RunPython kullanımı

RunPython ile migration içerisinde python fonksiyonu çalıştırabiliyoruz.

# Custom migration dosyasi ornegi:

from __future__ import unicode_literals
from django.db import migrations

def forwards_func(apps, schema_editor):
    AccountingSlip = apps.get_model("accounting", "AccountingSlip")
    # migration calistiginda calisir
    AccountingSlip.objects.create(...)

def reverse_func(apps, schema_editor):
    # migration'i geri aldigimizda calisir.
    AccountingSlip = apps.get_model("accounting", "AccountingSlip")
    AccountingSlip.objects.all().delete()

class Migration(migrations.Migration):
    dependencies = [...]

    operations = [
        # Custom migration 
        migrations.RunPython(forwards_func, reverse_func, atomic=True),
    ]

RunPython kullanırken bilmeniz gereken bir nokta RunPython‘un defaultta migration fonksiyonunun transaction bloğu içerisinde çalışmadığıdır. Fonksiyonu transaction bloğu içinde çalıştırmak için RunPython fonksiyonunu çalıştırırken atomic=True verebilirsiniz.

Migration geri alındığında ekstra herhangi bir işlem yapılmayacaksa, reverse_func yerine RunPython.noop kullanabilirsiniz.

RunSQL kullanımı

RunSQL migration içerisinde custom SQL çalıştırmamıza olanak sağlar.

    operations = [
        migrations.RunSQL(["UPDATE mytable set foo=bar"],  RunSQL.noop),
    ],

İhtiyacınıza göre RunPython veyada RunSQL kullanabilirsiniz. Ben sql ile kasmak yerine custom migrationları python ile yazmayı tercih ediyorum.


Bu yazıyı yazdığımda Django 1.11 kullanıyordum.

Kaynaklar:

comments powered by Disqus