Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este artigo explica como o sistema de migração do Django funciona com o SQL Server através do mssql-django backend e documenta os casos limites conhecidos.
Criar e aplicar migrações
O fluxo de trabalho de migração do Django funciona da mesma forma com o SQL Server que com outras bases de dados:
Gerar migrações a partir de alterações de modelo:
python manage.py makemigrations myappRevise os ficheiros de migração gerados em
<app>/migrations/.Aplicar migrações à base de dados:
python manage.py migrate myappVerifique o estado da migração:
python manage.py showmigrations myapp
Configuração inicial do projeto
Quando configuras um novo projeto Django com SQL Server, executa migrações para criar as tabelas integradas do Django (autenticação, sessões, administração):
python manage.py migrate
Este comando cria todas as tabelas exigidas pelas aplicações listadas em INSTALLED_APPS.
SQL personalizado em migrações
Use migrations.RunSQL para executar instruções SQL brutas durante migrações. Esta abordagem é útil para criar procedimentos armazenados, triggers ou outros objetos específicos do 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 de transição conhecidos
As seguintes operações de migração requerem soluções alternativas quando o destino é o SQL Server.
Alteração do AutoField
Alterar um campo de modelo de ou para AutoField no momento da migração não é suportado. O SQL Server não permite adicionar ou remover a IDENTITY propriedade de uma coluna existente.
Solução alternativa: Crie um novo modelo com o tipo de campo desejado. Migra dados da tabela antiga para a nova tabela e depois remove a tabela antiga.
Renomear campo ou modelo com restrições de chave estrangeira
Renomear um campo ou modelo que tenha restrições de chave estrangeira pode falhar. O SQL Server exige eliminar e recriar restrições FK durante as operações de renomeação.
Solução alternativa: Use migrations.SeparateDatabaseAndState para eliminar a restrição FK, renomear a coluna e recriar a restrição, enquanto diz ao Django para atualizar o estado do modelo. O exemplo seguinte renomeia a product chave estrangeira num Order modelo para 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 o nome real da restrição na tua base de dados antes de executar este código T-SQL. O Django gera nomes de restrições que incluem um hash curto, por isso o nome no seu esquema não corresponde ao marcador de posição mostrado aqui.
Migrações das abóboras
Depois de muitas migrações se acumularem, pode consolidá-las num número menor de ficheiros:
python manage.py squashmigrations myapp 0001 0010
Dica
Teste sempre migrações comprimidas contra uma base de dados nova para garantir que produzem o esquema correto.
Colunas geradas (colunas calculadas)
O backend mssql-django suporta o GeneratedField do Django (Django 5.0 e versões posteriores), que mapeia para colunas computadas do SQL Server.
Colunas geradas armazenadas (PERSISTENTES)
Uma coluna armazenada gerada é fisicamente escrita no disco e atualizada quando as colunas de origem mudam:
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,
)
Isto gera: total_price AS ([price] * (1 + [tax_rate])) PERSISTED.
Colunas geradas virtualmente
Uma coluna virtual gerada é calculada em tempo de consulta e não consome armazenamento:
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
O SQL Server restringe índices em colunas computadas não persistentes. Usa db_persist=True se precisares de indexar a coluna gerada.
Comentários de tabela e coluna
O mssql-django backend é compatível com a funcionalidade db_comment do Django (Django 4.2 e versões posteriores). Os comentários são armazenados como MS_Description propriedades estendidas no objeto SQL Server.
Comentários nas tabelas
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."
Comentários da coluna
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")
Os comentários são visíveis no SQL Server Management Studio, nas propriedades de colunas/tabelas e via sys.extended_properties.
Chaves primárias compostas
O Django 5.2 introduziu CompositePrimaryKey. O mssql-django backend tem suporte parcial para chaves primárias compostas, mas alguns casos de teste Django ainda estão excluídos. Valide as migrações e consultas com chaves compostas na sua aplicação antes de as adotar em produção.
-
inspectdbnão gera corretamente as chaves primárias compostas. Defina-os manualmente após a inspeção. - As consultas de tuplas não são suportadas. O backend decompõe as comparações de chaves compostas em condições individuais para cada coluna.
- A comparação de tuplas com subconsultas requer o Django 5.2.4 e versões posteriores.
- Algumas operações de migração ainda têm exclusões conhecidas. Consulte Limitações e funcionalidades não suportadas no mssql-django para o estado atual.
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 tratamento
Quando insere valores explícitos num AutoField (por exemplo, restaurando dados de um backup com IDs específicos), o backend envolve automaticamente o inserto emSET IDENTITY_INSERT ON / SET IDENTITY_INSERT OFF . Não é necessário SQL manual.
# The backend handles IDENTITY_INSERT automatically
Product.objects.create(id=42, name="Restored Widget", price=9.99)
Note
O SQL Server permite que apenas uma tabela por sessão tenha IDENTITY_INSERT ON de cada vez. Se inserires IDs explícitos em múltiplas tabelas num único bloco atomic(), o backend processa a alternância por instrução. No entanto, as sessões simultâneas que também utilizam IDENTITY_INSERT na mesma tabela podem entrar em conflito.