Engenharia inversa de modelos com inspectdb

Este artigo explica como usar o comando de gestão do inspectdb Django para gerar código de modelo a partir de uma base de dados SQL Server existente.

Pré-requisitos

Adicione mssql ao seu INSTALLED_APPS em settings.py. Este passo regista a substituição do comando de gestão mssql-django para inspectdb, que adiciona a opção --schema para inspecionar esquemas não predefinidos:

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "mssql",
    "myapp",
]

Note

O mssql backend da base de dados funciona sem este passo. Somar "mssql" a INSTALLED_APPS só é necessário para ativar a --schema flag em inspectdb. Sem ele, inspectdb inspeciona apenas o esquema padrão (dbo).

Utilização básica

Gerar modelos para todas as tabelas na base de dados configurada:

python manage.py inspectdb

Guardar a saída diretamente num ficheiro de modelos:

python manage.py inspectdb > myapp/models.py

Inspecionar tabelas específicas

Gerar modelos apenas para tabelas específicas:

python manage.py inspectdb MyTable AnotherTable

Suporte a múltiplos esquemas

O backend mssql-django estende inspectdb para suportar múltiplos esquemas. Especifique um esquema com o --schema flag:

python manage.py inspectdb --schema "dbo"
python manage.py inspectdb --schema "sales"

Esta funcionalidade é útil para bases de dados SQL Server que organizam tabelas em múltiplos esquemas.

Trabalho com modelos de múltiplos esquemas

Quando a sua base de dados usa múltiplos esquemas, use db_table na classe do Meta modelo para qualificar a tabela com o nome do seu esquema. Modelos gerados a partir inspectdb podem não incluir prefixos de esquema, por isso adicione-os manualmente:

class Customer(models.Model):
    customer_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=200)

    class Meta:
        managed = False
        db_table = "[sales].[Customer]"

class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        managed = False
        db_table = "[inventory].[Product]"

Importante

Use um nome de duas partes com parênteses como "[schema].[table]". O backend trata db_table como um único identificador, pelo que os nomes entre colchetes são preservados corretamente, enquanto as formas com aspas duplas são novamente colocadas entre aspas como um nome literal de tabela.

Chaves estrangeiras entre esquemas

O Django pode seguir relações de chave estrangeira entre esquemas desde que ambas as tabelas estejam na mesma base de dados e os db_table valores estejam corretamente definidos:

class OrderItem(models.Model):
    order_item_id = models.AutoField(primary_key=True)
    product = models.ForeignKey("Product", on_delete=models.CASCADE)
    quantity = models.IntegerField()

    class Meta:
        managed = False
        db_table = "[sales].[OrderItem]"

O Django resolve o ForeignKey através do valor do db_table modelo referenciado, pelo que não é necessária uma configuração adicional do esquema no campo de relação.

Reveja os modelos gerados

O inspectdb comando gera código de modelo que pode necessitar de ajustes manuais:

  1. Set managed = False: Os modelos gerados incluem managed = False na Meta classe, o que significa que o Django não gere o esquema da tabela. Remove esta linha se quiseres que o Django gere as migrações da tabela.

  2. Adicionar chaves primárias: Se uma tabela não tiver uma chave primária que inspectdb possa detetar, pode ser necessário adicionar uma manualmente.

  3. Corrigir campos de relação: Relações de chave estrangeira podem precisar de ajuste, especialmente para referências entre esquemas.

Exemplo de saída gerada:

class Product(models.Model):
    product_id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    created_at = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = "Product"

Limitations

O inspectdb comando apresenta as seguintes limitações quando usado com o SQL Server.

Verificação da chave primária composta

Tabelas com chaves primárias compostas podem não gerar definições completas do modelo. No Django 5.2 e posteriores, defina CompositePrimaryKey manualmente após executar inspectdb, ou use uma chave primária substituta.

Views

O inspectdb comando pode inspecionar vistas, mas os modelos gerados podem exigir ajuste manual dos tipos de campo e das restrições nulas.