Back-end do Django para SQL Server - mssql-django

mssql-djangoé o back-end do banco de dados Django do Microsoft para SQL Server, Banco de Dados SQL do Azure, Instância Gerenciada de SQL do Azure e banco de dados SQL no Microsoft Fabric. Defina ENGINE como "mssql" na configuração do Django DATABASES para se conectar. O back-end baseia-se no pyodbc e no Microsoft ODBC Driver for SQL Server e dá suporte ao Django 3.2 a 6.0, Python 3.8 a 3.14 e SQL Server 2016 a 2025.

Escolha o ponto de partida

Linha de base de produção para SQL do Azure

Use esse snippet como ponto de partida para uma configuração de SQL do Azure orientada à produção. Ele combina quatro arquivos: settings.py (a configuração do banco de dados do Django, o registro de middleware e o registro em log), myproject/retry.py (o catálogo de erros transitórios e retry_on_transient o decorador), myproject/middleware.py (o middleware de repetição no nível da solicitação) e myapp/views.py (um exemplo de exibição transacional).

# settings.py

import logging.config
import os

DATABASES = {
    "default": {
        "ENGINE": "mssql",
        "NAME": os.environ["SQL_DATABASE"],          # for example, appdb
        "HOST": os.environ["SQL_SERVER"],            # for example, contoso.database.windows.net
        "PORT": "1433",
        "CONN_MAX_AGE": 300,                         # reuse pooled connections for 5 minutes
        "CONN_HEALTH_CHECKS": True,                  # validate connections before reuse (Django 4.1 and later)
        "ATOMIC_REQUESTS": False,                    # wrap mutating views in transactions explicitly (see the following view example)
        "OPTIONS": {
            "driver": "ODBC Driver 18 for SQL Server",
            "extra_params": (
                "Authentication=ActiveDirectoryMsi;"
                "Encrypt=yes;"
                "TrustServerCertificate=no;"
                # ODBC driver reconnects connections dropped while idle.
                "ConnectRetryCount=3;"
                "ConnectRetryInterval=10;"
            ),
            # Backend-level retry for the initial connect call. Complements
            # ConnectRetryCount, which only covers idle drops on an
            # already-established connection.
            # See Retry logic and connection resilience for the recognized error list.
            "connection_retries": 3,
            "connection_retry_backoff_time": 5,
        },
    },
}

MIDDLEWARE = [
    # Defined in myproject/middleware.py. Catches transient OperationalErrors
    # and retries the request. Add "1205" (deadlock victim) and "1222"
    # (lock-request timeout) to TRANSIENT_ERROR_CODES to also retry
    # statement-level failures.
    "myproject.middleware.DatabaseRetryMiddleware",
    "django.middleware.security.SecurityMiddleware",
    # ... your other middleware
]

LOGGING_CONFIG = None
logging.config.dictConfig({
    "version": 1,
    "disable_existing_loggers": False,
    "formatters": {
        "json": {
            "format": (
                '{"time":"%(asctime)s","level":"%(levelname)s",'
                '"logger":"%(name)s","message":"%(message)s"}'
            ),
        },
    },
    "handlers": {
        "console": {
            "class": "logging.StreamHandler",
            "formatter": "json",
        },
    },
    "loggers": {
        "django.db.backends": {
            "handlers": ["console"],
            "level": "WARNING",      # raise to INFO or DEBUG to capture SQL
            "propagate": False,
        },
        "django.request": {
            "handlers": ["console"],
            "level": "WARNING",
            "propagate": False,
        },
        "mssql": {
            "handlers": ["console"],
            "level": "INFO",
            "propagate": False,
        },
    },
})

Defina o catálogo compartilhado de erros transitórios e o decorador retry_on_transient em myproject/retry.py:

# myproject/retry.py
import functools
import logging
import random
import re
import time

from django.db import OperationalError, connection

logger = logging.getLogger(__name__)

TRANSIENT_ERROR_CODES = {
    "64", "233", "4221",
    "10053", "10054", "10928", "10929",
    "40197", "40501", "40613",
    "49918", "49919", "49920",
    # Add "4060" only if targeting Azure SQL with geo-replication failover.
    # Add "1205" (deadlock victim) and "1222" (lock-request timeout) to
    # also retry statement-level failures.
}

# Microsoft ODBC driver formats native error codes as "(<number>)" in the
# message. Parenthesized matches avoid false positives for short codes like "64".
_CODE_RE = re.compile(r"\((\d+)\)")


def is_transient(error):
    codes_in_message = set(_CODE_RE.findall(str(error)))
    return bool(codes_in_message & TRANSIENT_ERROR_CODES)


def retry_on_transient(max_retries=3, base_delay=1, max_delay=30):
    """Retry on transient database errors with exponential backoff and full jitter."""

    def decorator(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries + 1):
                try:
                    return func(*args, **kwargs)
                except OperationalError as e:
                    if attempt < max_retries and is_transient(e):
                        capped = min(max_delay, base_delay * (2 ** attempt))
                        delay = random.uniform(0, capped)
                        logger.warning(
                            "Transient error in %s (attempt %d/%d), retrying in %.2fs: %s",
                            func.__name__, attempt + 1, max_retries, delay, e
                        )
                        connection.close()
                        time.sleep(delay)
                        continue
                    raise
        return wrapper
    return decorator

Defina o middleware no nível da solicitação em myproject/middleware.py. Ele reutiliza is_transient para que ambas as camadas reconheçam o mesmo conjunto de códigos de erro:

# myproject/middleware.py
import logging
import random
import time

from django.db import OperationalError, connection

from myproject.retry import is_transient

logger = logging.getLogger(__name__)


class DatabaseRetryMiddleware:
    """Retry the entire request on transient database errors."""

    def __init__(self, get_response):
        self.get_response = get_response
        self.max_retries = 3
        self.base_delay = 1   # seconds; doubled each attempt
        self.max_delay = 30   # cap on a single sleep, regardless of attempt

    def __call__(self, request):
        for attempt in range(self.max_retries + 1):
            try:
                return self.get_response(request)
            except OperationalError as e:
                if attempt < self.max_retries and is_transient(e):
                    capped = min(self.max_delay, self.base_delay * (2 ** attempt))
                    delay = random.uniform(0, capped)
                    logger.warning(
                        "Transient DB error (attempt %d/%d), retrying in %.2fs: %s",
                        attempt + 1, self.max_retries, delay, e
                    )
                    connection.close()
                    time.sleep(delay)
                    continue
                raise

Como ATOMIC_REQUESTS é False, as visualizações modificáveis devem abrir uma transação própria. Encapsule o bloco atomic() com @retry_on_transient para que cada tentativa execute uma nova transação:

# myapp/views.py
from django.db import transaction
from django.http import JsonResponse

from myproject.retry import retry_on_transient
from .models import Order


# Exponential backoff with full jitter: sleeps random within [0,2], [0,4], [0,8] seconds.
@retry_on_transient(max_retries=3, base_delay=2)
def submit_order(request, order_id):
    with transaction.atomic():
        order = Order.objects.select_for_update().get(id=order_id)
        order.status = "submitted"
        order.save()
    return JsonResponse({"id": order.id, "status": order.status})

Note

Esta configuração base registra tentativas de repetição em dois níveis. O middleware atua como uma salvaguarda para o acesso ao banco de dados fora das views decoradas, como a interface de administração, sinais ou outros middlewares. O @retry_on_transient decorador dá aos autores de visualizações um controle mais granular sobre quais operações serão repetidas. Se um erro transitório escapar do decorador, o middleware tentará novamente toda a solicitação, de modo que, no pior caso, pode haver até nove tentativas antes de o cliente receber um erro. Se esse teto for alto demais para o seu orçamento de latência, remova uma camada ou reduza max_retries na camada que você mantiver.

Para obter mais informações sobre cada parte dessa configuração, consulte Referência de configuração, opções de conexão, pool de conexões, lógica de repetição e resiliência de conexão e autenticação Microsoft Entra.

Características principais

  • Backend plugável para Django: Defina ENGINE como "mssql" e o ORM, as migrações, o admin e os comandos de gerenciamento do Django funcionarão com o SQL Server.
  • Baseado em pyodbc e ODBC Driver 18: conexões criptografadas por TLS por padrão e suporte amplo à plataforma em Windows, Linux e macOS.
  • Matriz de versão ampla: Django 3.2 a 6.0, Python 3.8 a 3.14 e SQL Server 2016 a 2025.
  • Autenticação do Microsoft Entra ID: conexões sem senha com identidade gerenciada, principal de serviço e fluxos interativos e integrados via extra_params.
  • Migrações do Django: migrações de esquema para o SQL Server, incluindo tipos de coluna específicos do SQL Server.
  • Suporte a JSONField: nativo JSONField apoiado pelo armazenamento nvarchar(max) e pesquisas do Django.
  • Always Encrypted: criptografia do lado do cliente para colunas confidenciais.
  • Operações em massa: bulk_create e bulk_update no SQL Server com tamanhos de lote adequados.
  • Repetição transitória: tratamento interno para erros comuns SQL do Azure transitórios durante a conexão e a execução da consulta.
  • inspectdb: gere modelos do Django de esquemas de SQL Server existentes.

Introdução

Artigo Descrição
Installation Instale mssql-django e o driver ODBC da Microsoft para SQL Server.
Início Rápido: Conectar o Django ao SQL Server Conecte um projeto do Django para SQL Server e execute sua primeira migração.

Configuração e conexão

Artigo Descrição
Referência de configuração Referência completa para o dicionário Django DATABASES com mssql-django.
Opções de conexão OPTIONS, extra_paramstempos limite e configuração do driver ODBC.
Agrupamento de conexões CONN_MAX_AGE, CONN_HEALTH_CHECKS, e integração com pool externo.
Lógica de repetição e resiliência da conexão Detecte erros transitórios e tente novamente conexões e consultas.
Autenticação do Microsoft Entra Autenticação sem senha com identidade gerenciada, entidade de serviço, fluxos interativos e integrados.
Melhores práticas de segurança Parametrização, gerenciamento de segredos, privilégio mínimo e criptografia.
Always Encrypted Configure a criptografia do lado do cliente para colunas confidenciais.

Modelos, migrações e tipos de dados

Artigo Descrição
Migrações de banco de dados Execute migrações do Django no SQL Server, incluindo tipos de coluna específicos do SQL Server.
Mapeamentos de tipos de campos do Django para tipos do SQL Server Como os campos de modelo do Django são mapeados para os tipos de dados do SQL Server.
Suporte do JSONField Use JSONField com SQL Server e pesquisas do Django.
Faça engenharia reversa de modelos com inspectdb Gere modelos do Django a partir de esquemas de SQL Server existentes.
Suporte a fuso horário USE_TZ, datetimeoffset e valores de data e hora que reconhecem o fuso horário.

Consultar e trabalhar com dados

Artigo Descrição
Operações em lote bulk_create, bulk_updatee ajuste do tamanho do lote.
Gerenciamento de transações atomic, níveis de isolamento, pontos de salvamento e manipulação de deadlock.
Consultas SQL brutas RawSQL, connection.cursor() e a sintaxe específica do SQL Server.
Procedimentos armazenados Chame procedimentos armazenados do SQL Server a partir do Django.

Implantar, testar e ajustar

Artigo Descrição
Implantar no Serviço de Aplicativo do Azure Envie um site do Django para Serviço de Aplicativo do Azure com mssql-django.
Contêiner e desenvolvimento local Contêineres Docker, devcontainers e pipelines de CI para Django + SQL Server.
Testando Execute pacotes de teste do Django em SQL Server.
Otimização do desempenho Índices, padrões de consulta, reutilização de conexão e tamanhos de lote.
Solução de problemas Erros comuns, diagnóstico ODBC e log.

Migrar para mssql-django

Artigo Descrição
Migrar do django-mssql-backend Migrar do pacote da comunidade django-mssql-backend para mssql-django.
Migrar de outros bancos de dados Mova um projeto do Django de outro back-end de banco de dados para SQL Server.
Migrar do PostgreSQL Guia de parada única para desenvolvedores do Django que migram do PostgreSQL para o SQL Server.
Artigo Descrição
Ciclo de vida do suporte Versões com suporte de Django, Python e SQL Server.
Novidades Histórico de versões e destaques da versão.
Limitações e recursos sem suporte no mssql-django Limitações de back-end e recursos sem suporte.
perguntas frequentes Perguntas frequentes.