Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
In dit artikel wordt uitgelegd hoe Django's migratiesysteem werkt met SQL Server via de mssql-django backend en worden bekende randgevallen gedocumenteerd.
Migraties maken en toepassen
De migratiewerkstroom van Django werkt op dezelfde manier met SQL Server als bij andere databases:
Migraties genereren van modelwijzigingen:
python manage.py makemigrations myappControleer de gegenereerde migratiebestanden in
<app>/migrations/.Migraties toepassen op de database:
python manage.py migrate myappMigratiestatus controleren:
python manage.py showmigrations myapp
Initiële projectconfiguratie
Wanneer u een nieuw Django-project instelt met SQL Server, voert u migraties uit om de ingebouwde tabellen van Django te maken (verificatie, sessies, beheerder):
python manage.py migrate
Met deze opdracht worden alle tabellen gemaakt die vereist zijn voor apps die worden vermeld in INSTALLED_APPS.
Aangepaste SQL in migraties
Gebruik migrations.RunSQL dit om onbewerkte SQL-instructies uit te voeren tijdens migraties. Deze methode is handig voor het maken van opgeslagen procedures, triggers of andere SQL Server-specifieke objecten:
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;",
),
]
Bekende randgevallen bij migratie
Voor de volgende migratiebewerkingen zijn tijdelijke oplossingen nodig wanneer SQL Server als doeldatabase wordt gebruikt.
AutoField-wijziging
Het wijzigen van een modelveld van of naar AutoField tijdens de migratie wordt niet ondersteund. SQL Server staat het toevoegen of verwijderen van de IDENTITY eigenschap niet toe uit een bestaande kolom.
Tijdelijke oplossing: Maak een nieuw model met het gewenste veldtype. Migreer gegevens van de oude tabel naar de nieuwe tabel en zet de oude tabel neer.
De naam van een veld of model wijzigen met foreign key-beperkingen
Het wijzigen van de naam van een veld of model met foreign key-beperkingen kan mislukken. SQL Server moet FK-beperkingen verwijderen en opnieuw maken tijdens hernoembewerkingen.
Tijdelijke oplossing: Gebruik migrations.SeparateDatabaseAndState om de FK-constraint te verwijderen, de kolom te hernoemen en de constraint opnieuw aan te maken, en geef daarbij aan dat Django de modelstatus moet bijwerken. In het volgende voorbeeld wordt de product vreemde sleutel op een Order-model hernoemd naar item:
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",
),
],
),
]
Zoek de werkelijke naam van de beperking in uw database op voordat u deze T-SQL-code uitvoert. Django genereert constraintnamen met een korte hash, waardoor de naam in uw schema niet overeenkomt met de placeholder die hier wordt weergegeven.
Migraties squashen
Nadat veel migraties zich hebben verzameld, kunt u ze in minder bestanden opnemen:
python manage.py squashmigrations myapp 0001 0010
Tip
Test gestaakte migraties altijd op basis van een nieuwe database om ervoor te zorgen dat ze het juiste schema produceren.
Gegenereerde kolommen (berekende kolommen)
De mssql-django backend ondersteunt Django's GeneratedField (Django 5.0 en later), die overeenkomt met berekende kolommen in SQL Server.
Opgeslagen (PERSISTENTED) gegenereerde kolommen
Een opgeslagen gegenereerde kolom wordt fysiek naar schijf geschreven en bijgewerkt wanneer de bronkolommen veranderen:
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,
)
Hiermee wordt het volgende gegenereerd: total_price AS ([price] * (1 + [tax_rate])) PERSISTED.
Virtuele gegenereerde kolommen
Een virtuele gegenereerde kolom wordt berekend op het moment van de query en verbruikt geen opslag:
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 beperkt indexen op niet-persistente berekende kolommen. Gebruik db_persist=True deze optie als u de gegenereerde kolom moet indexeren.
Tabel- en kolomopmerkingen
De mssql-django back-end ondersteunt de functie van db_comment Django (Django 4.2 en hoger). Opmerkingen worden opgeslagen als MS_Description uitgebreide eigenschappen op het SQL Server-object.
Tabelopmerkingen
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."
Kolomopmerkingen
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")
Opmerkingen zijn zichtbaar in SQL Server Management Studio onder kolom-/tabeleigenschappen en via sys.extended_properties.
Samengestelde primaire sleutels
Django 5.2 geïntroduceerd CompositePrimaryKey. De mssql-django back-end biedt gedeeltelijke ondersteuning voor samengestelde primaire sleutels, maar sommige Django-testcases worden nog steeds uitgesloten. Valideer migraties en query's met samengestelde sleutels voor uw toepassing voordat u ze in productie neemt.
-
inspectdbgenereert samengestelde primaire sleutels niet correct. Definieer ze handmatig na inspectie. - Tuple-zoekacties worden niet ondersteund. In de back-end worden samengestelde sleutelvergelijkingen opgesplitst in afzonderlijke kolomvoorwaarden.
- Voor vergelijking van tuples met subquery’s zijn Django 5.2.4 en nieuwere versies vereist.
- Sommige migratiebewerkingen hebben nog steeds bekende uitsluitingen. Zie Beperkingen en niet-ondersteunde functies in mssql-django voor de huidige status.
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 Behandeling
Wanneer u in een AutoField expliciete waarden invoegt (bijvoorbeeld bij het herstellen van gegevens uit een back-up met specifieke ID's), verpakt de backend de invoegbewerking automatisch in SET IDENTITY_INSERT ON / SET IDENTITY_INSERT OFF. Er is geen handmatige SQL nodig.
# The backend handles IDENTITY_INSERT automatically
Product.objects.create(id=42, name="Restored Widget", price=9.99)
Note
SQL Server staat toe dat slechts één tabel per sessie tegelijk IDENTITY_INSERT ON heeft. Als u expliciete ID’s in meerdere tabellen in één atomic()-blok invoegt, verwerkt de backend de omschakeling per statement. Gelijktijdige sessies die ook IDENTITY_INSERT op dezelfde tabel gebruiken, kunnen echter met elkaar conflicteren.