mssql-django ile veritabanı geçişleri

Bu makale, Django'nun geçiş sisteminin SQL Server ile mssql-django arka ucu üzerinden nasıl çalıştığını açıklar ve bilinen uç durumları belgelendirir.

Migrasyonları oluşturun ve uygulayın

Django'nun geçiş iş akışı, diğer veritabanlarında olduğu gibi SQL Server ile aynı şekilde çalışır:

  1. Model değişikliklerinden geçişler oluşturun:

    python manage.py makemigrations myapp
    
  2. içinde <app>/migrations/oluşturulan geçiş dosyalarını gözden geçirin.

  3. Veritabanına geçişleri uygulama:

    python manage.py migrate myapp
    
  4. Geçiş durumunu denetleyin:

    python manage.py showmigrations myapp
    

İlk proje kurulumu

SQL Server ile yeni bir Django projesi ayarladığınızda, Django'nun yerleşik tablolarını (kimlik doğrulaması, oturumlar, yönetici) oluşturmak için geçişleri çalıştırın:

python manage.py migrate

Bu komut, içinde INSTALLED_APPSlistelenen uygulamalar için gereken tüm tabloları oluşturur.

Geçişlerde özel SQL

Geçişler sırasında ham SQL deyimlerini yürütmek için kullanın migrations.RunSQL . Bu yaklaşım saklı yordamlar, tetikleyiciler veya SQL Server özgü diğer nesneler oluşturmak için kullanışlıdır:

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ("myapp", "0001_initial"),
    ]

    operations = [
        migrations.RunSQL(
            sql="CREATE INDEX IX_myapp_product_name ON myapp_product (name);",
            reverse_sql="DROP INDEX IX_myapp_product_name ON myapp_product;",
        ),
    ]

Bilinen geçiş uç durumları

Aşağıdaki geçiş işlemleri, SQL Server hedeflerken geçici çözümler gerektirir.

AutoField değişikliği

Bir model alanının geçiş sırasında AutoField değerinden veya AutoField değerine değiştirilmesi desteklenmez. SQL Server özelliğin mevcut bir sütuna eklenmesine veya kaldırılmasına IDENTITY izin vermez.

Geçici çözüm: İstenen alan türüne sahip yeni bir model oluşturun. Verileri eski tablodan yeni tabloya geçirin ve eski tabloyu bırakın.

Yabancı anahtar kısıtlamalarıyla alanı veya modeli yeniden adlandırma

Yabancı anahtar kısıtlamaları olan bir alanı veya modeli yeniden adlandırma işlemi başarısız olabilir. SQL Server, yeniden adlandırma işlemleri sırasında FK kısıtlamalarının bırakılıp yeniden oluşturmasını gerektirir.

Geçici çözüm: Django'ya model durumunu güncelleştirmesini bildirirken FK kısıtlamasını bırakmak, sütunu yeniden adlandırmak ve kısıtlamayı yeniden oluşturmak için kullanın migrations.SeparateDatabaseAndState . Aşağıdaki örnek, bir Order modelindeki product yabancı anahtarının adını item olarak değiştirir:

from django.db import migrations

class Migration(migrations.Migration):

    dependencies = [
        ("myapp", "0002_previous"),
    ]

    operations = [
        migrations.SeparateDatabaseAndState(
            database_operations=[
                migrations.RunSQL(
                    sql="ALTER TABLE myapp_order DROP CONSTRAINT FK_order_product;",
                    reverse_sql="ALTER TABLE myapp_order ADD CONSTRAINT FK_order_product FOREIGN KEY (product_id) REFERENCES myapp_product(id);",
                ),
                migrations.RunSQL(
                    sql="EXECUTE sp_rename 'myapp_order.product_id', 'item_id', 'COLUMN';",
                    reverse_sql="EXECUTE sp_rename 'myapp_order.item_id', 'product_id', 'COLUMN';",
                ),
                migrations.RunSQL(
                    sql="ALTER TABLE myapp_order ADD CONSTRAINT FK_order_item FOREIGN KEY (item_id) REFERENCES myapp_product(id);",
                    reverse_sql="ALTER TABLE myapp_order DROP CONSTRAINT FK_order_item;",
                ),
            ],
            state_operations=[
                migrations.RenameField(
                    model_name="order",
                    old_name="product",
                    new_name="item",
                ),
            ],
        ),
    ]

Bu T-SQL kodunu çalıştırmadan önce veritabanınızda gerçek kısıtlama adını arayın. Django, kısa bir karma değer içeren kısıtlama adları oluşturur; bu nedenle şemanızdaki ad, burada gösterilen yer tutucu adla eşleşmez.

Squash geçişleri

Birçok geçiş biriktirildikten sonra bunları daha az dosyaya sıkıştırabilirsiniz:

python manage.py squashmigrations myapp 0001 0010

Tip

Doğru şemayı ürettiklerinden emin olmak için sıkıştırılan geçişleri her zaman yeni bir veritabanına karşı test edin.

Oluşturulan sütunlar (hesaplanan sütunlar)

mssql-django arka ucu, SQL Server’daki hesaplanan sütunlarla eşlenen Django’nun GeneratedField özelliğini destekler (Django 5.0 ve sonrası).

Saklanan (KALICI) üretilen sütunlar

Depolanan bir sütun fiziksel olarak diske yazılır ve kaynak sütunlar değiştiğinde güncelleştirilir:

from django.db import models
from django.db.models import F

class Product(models.Model):
    price = models.DecimalField(max_digits=10, decimal_places=2)
    tax_rate = models.DecimalField(max_digits=5, decimal_places=4)
    total_price = models.GeneratedField(
        expression=F("price") * (1 + F("tax_rate")),
        output_field=models.DecimalField(max_digits=10, decimal_places=2),
        db_persist=True,
    )

Bu şunu oluşturur: total_price AS ([price] * (1 + [tax_rate])) PERSISTED.

Sanal olarak oluşturulan sütunlar

Sanal olarak oluşturulan bir sütun sorgu zamanında hesaplanır ve depolama kullanmaz:

from django.db import models
from django.db.models import F, Value
from django.db.models.functions import Concat

class Employee(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    full_name = models.GeneratedField(
        expression=Concat(F("first_name"), Value(" "), F("last_name")),
        output_field=models.CharField(max_length=101),
        db_persist=False,
    )

Note

SQL Server kalıcı olmayan hesaplanmış sütunlardaki dizinleri kısıtlar. Oluşturulan sütunu dizine almanız gerekiyorsa kullanın db_persist=True .

Tablo ve sütun açıklamaları

mssql-django Arka uç, Django'nun db_comment özelliğini (Django 4.2 ve üzeri) destekler. Açıklamalar, SQL Server nesnesinde genişletilmiş özellikler olarak MS_Description depolanır.

Tablo açıklamaları

class AuditLog(models.Model):
    action = models.CharField(max_length=50)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table_comment = "Tracks user actions for compliance auditing."

Sütun açıklamaları

class Measurement(models.Model):
    value = models.FloatField(db_comment="Sensor reading in Celsius")
    recorded_at = models.DateTimeField(db_comment="UTC timestamp from the data logger")

Açıklamalar, SQL Server Management Studio’da sütun/tablo özelliklerinde ve sys.extended_properties üzerinden görülebilir.

Bileşik birincil anahtarlar

Django 5.2 tanıtıldı CompositePrimaryKey. mssql-django arka uç, bileşik birincil anahtarları kısmen destekler, ancak bazı Django test durumları hâlâ hariç tutulmaktadır. Bunları üretimde kullanıma almadan önce, bileşik anahtar geçişlerini ve sorgularını uygulamanız üzerinde doğrulayın.

  • inspectdb bileşik birincil anahtarları doğru oluşturmaz. İncelemeden sonra bunları el ile tanımlayın.
  • Tanımlama grubu aramaları desteklenmez. Arka uç, bileşik anahtar karşılaştırmalarını tek tek sütun koşullarına ayırır.
  • Alt sorgulara karşı demet karşılaştırması için Django 5.2.4 ve sonraki sürümler gerekir.
  • Bazı geçiş işlemleri hâlâ bilinen istisnalar içerir. Geçerli durum için bkz. mssql-django'da sınırlamalar ve desteklenmeyen özellikler .
from django.db import models
from django.db.models import CompositePrimaryKey

class OrderItem(models.Model):
    pk = CompositePrimaryKey("order_id", "product_id")
    order = models.ForeignKey("Order", on_delete=models.CASCADE)
    product = models.ForeignKey("Product", on_delete=models.CASCADE)
    quantity = models.IntegerField()

IDENTITY_INSERT işleme

Bir AutoField içine açık değerler eklediğinizde (örneğin, belirli kimliklerle bir yedekten verileri geri yüklerken), arka uç ekleme işlemini otomatik olarak SET IDENTITY_INSERT ON / SET IDENTITY_INSERT OFF içine alır. El ile SQL gerekmez.

# The backend handles IDENTITY_INSERT automatically
Product.objects.create(id=42, name="Restored Widget", price=9.99)

Note

SQL Server, oturum başına aynı anda yalnızca bir tabloda IDENTITY_INSERT ON bulunmasına izin verir. Tek bir atomic() bloğunda birden çok tabloya kimlikleri açıkça belirtirseniz, arka uç açma/kapatma işlemini her ifade için ayrı ayrı gerçekleştirir. Ancak, aynı tabloda IDENTITY_INSERT kullanan diğer eşzamanlı oturumlar çakışabilir.