Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Este artículo explica cómo funciona el sistema de migración de Django con SQL Server a través del mssql-django backend y documenta los casos límite.
Crear y aplicar migraciones
El flujo de trabajo de migración de Django funciona de la misma manera con SQL Server que con otras bases de datos:
Generar migraciones a partir de cambios de modelo:
python manage.py makemigrations myappRevise los archivos de migración generados en
<app>/migrations/.Aplique migraciones a la base de datos:
python manage.py migrate myappCompruebe el estado de la migración:
python manage.py showmigrations myapp
Configuración inicial del proyecto
Al configurar un nuevo proyecto de Django con SQL Server, ejecute migraciones para crear tablas integradas de Django (autenticación, sesiones, administrador):
python manage.py migrate
Este comando crea todas las tablas necesarias para las aplicaciones enumeradas en INSTALLED_APPS.
SQL personalizado en migraciones
Use migrations.RunSQL para ejecutar instrucciones SQL sin procesar durante las migraciones. Este enfoque es útil para crear procedimientos almacenados, desencadenadores u otros objetos específicos de SQL Server:
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;",
),
]
Casos extremos de migración
Las siguientes operaciones de migración requieren soluciones alternativas cuando el destino es SQL Server.
Modificación de AutoField
No se admite la modificación de un campo de modelo de o a AutoField en el momento de la migración. SQL Server no permite agregar ni quitar la IDENTITY propiedad de una columna existente.
Solución alternativa: cree un nuevo modelo con el tipo de campo deseado. Migre datos de la tabla antigua a la nueva tabla y, a continuación, quite la tabla anterior.
Cambiar el nombre del campo o modelo con restricciones de clave externa
Se puede producir un error al cambiar el nombre de un campo o modelo que tenga restricciones de clave externa. SQL Server requiere quitar y volver a crear restricciones de FK durante las operaciones de cambio de nombre.
Solución alternativa: use migrations.SeparateDatabaseAndState para quitar la restricción FK, cambiar el nombre de la columna y volver a crear la restricción, al tiempo que indica a Django que actualice su estado del modelo. En el ejemplo siguiente se cambia el nombre de la product clave externa de un Order modelo a 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",
),
],
),
]
Consulta el nombre real de la restricción en tu base de datos antes de ejecutar este código Transact-SQL (T-SQL). Django genera nombres de restricción que incluyen un hash corto, por lo que el nombre del esquema no coincide con el marcador de posición que se muestra aquí.
Acciones referenciales a nivel de base de datos
Django 6.1 añade acciones referenciales a nivel de base de datos como DB_CASCADE, DB_SET_NULL, y DB_SET_DEFAULT. SQL Server rechaza grafos de clave foránea con múltiples rutas en cascada hacia la misma tabla, por lo que mssql-django no soporta estos valores en ninguna versión de SQL Server. Usar uno de estos valores eleva la comprobación fields.E324del sistema Django . Utiliza el comportamiento estándar a nivel on_delete de Django en su lugar.
Agregaciones a nivel de bit
Django 6.1 añade BitAnd, BitOr, y BitXor. SQL Server no tiene función nativa de agregado bit a bit y mssql-django no emula estos agregados. Llamarlos aumenta NotSupportedErrorel sueldo.
Migraciones agrupadas
Después de que se acumulan muchas migraciones, puede aplastarlas en menos archivos:
python manage.py squashmigrations myapp 0001 0010
Tip
Comprueba siempre las migraciones agrupadas en una base de datos nueva para asegurarte de que generan el esquema correcto.
Columnas generadas (columnas calculadas)
El mssql-django backend admite las GeneratedField de Django, que se corresponden con columnas calculadas de SQL Server.
Columnas generadas almacenadas (PERSISTED)
Una columna generada almacenada se escribe físicamente en el disco y se actualiza cuando cambian las columnas de origen:
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,
)
Esto genera: [total_price] AS (([price] * (1 + [tax_rate]))) PERSISTED. SQL Server normaliza la expresión cuando la almacena, por lo que sys.computed_columns muestra ([price]*((1)+[tax_rate])).
Columnas generadas virtuales
Una columna generada virtual se calcula en el momento de la consulta y no consume almacenamiento:
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 restringe los índices en columnas calculadas no persistentes. Use db_persist=True si necesita indexar la columna generada.
Comentarios de tabla y columna
El mssql-django backend admite la función db_comment de Django en las versiones de Django compatibles. Los comentarios se almacenan como MS_Description propiedades extendidas en el objeto SQL Server.
Comentarios sobre la tabla
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."
Comentarios de columna
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")
Los comentarios están visibles en SQL Server Management Studio en las propiedades de columna o tabla y a través de sys.extended_properties.
Claves principales compuestas
Django 5.2 introdujo CompositePrimaryKey. El mssql-django back-end tiene compatibilidad parcial con claves principales compuestas, pero todavía se excluyen algunos casos de prueba de Django. Valide las migraciones y consultas de clave compuesta en la aplicación antes de adoptarlas en producción.
-
inspectdbno genera correctamente claves principales compuestas. Defínalos manualmente tras la inspección. - No se admiten búsquedas en tuplas. El backend descompone las comparaciones de claves compuestas en condiciones individuales por columna.
- La comparación de tuplas con subconsultas requiere Django 5.2.4 y versiones posteriores.
- Algunas operaciones de migración todavía tienen exclusiones conocidas. Consulte Limitaciones y características no admitidas en mssql-django para obtener el estado actual.
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()
Manejo de IDENTITY_INSERT
Al insertar valores explícitos en un objeto AutoField (por ejemplo, al restaurar datos de una copia de seguridad con identificadores específicos), el backend envuelve automáticamente la inserción en SET IDENTITY_INSERT ON / SET IDENTITY_INSERT OFF. No se necesita SQL manual.
# The backend handles IDENTITY_INSERT automatically
Product.objects.create(id=42, name="Restored Widget", price=9.99)
Note
SQL Server permite que solo una tabla por sesión tenga IDENTITY_INSERT ON a la vez. Si insertas ID explícitos en varias tablas en un único bloque atomic(), el backend administra el cambio por cada instrucción. Sin embargo, las sesiones simultáneas que también usan IDENTITY_INSERT en la misma tabla pueden entrar en conflicto.