Django backend pro SQL Server - mssql-django

mssql-django je databázový backend Django od Microsoftu pro SQL Server, Azure SQL Database, Azure SQL Managed Instance a SQL databázi v Microsoft Fabric. Nastavte ENGINE na "mssql" v konfiguraci Django DATABASES, abyste se mohli připojit. Back-end vychází z pyodbc a ovladače ODBC Microsoft pro SQL Server a podporuje Django 3.2 až 6.0, Python 3.8 až 3.14 a SQL Server 2016 až 2025.

Výběr výchozího bodu

Směrný plán výroby pro Azure SQL

Tento fragment kódu použijte jako výchozí bod pro konfiguraci Azure SQL orientované na produkční prostředí. Kombinuje čtyři soubory: settings.py (konfigurace databáze Django, registrace middlewaru a protokolování), myproject/retry.py (katalog přechodných chyb a retry_on_transient dekorátor), myproject/middleware.py (middleware na úrovni požadavku) a myapp/views.py (příklad transakčního zobrazení).

# 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,
        },
    },
})

Definujte sdílený katalog přechodných chyb a dekorátor retry_on_transient v 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

Definujte middleware na úrovni požadavku v souboru myproject/middleware.py. Znovu se používá is_transient , aby obě vrstvy rozpoznaly stejnou sadu kódů chyb:

# 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

Protože ATOMIC_REQUESTS je False, zobrazení, která provádějí změny, musí otevřít vlastní transakci. Obalte blok atomic() pomocí @retry_on_transient, aby každý opakovaný pokus spustil novou transakci:

# 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

Tato základní konfigurace nastavuje opakování na dvou úrovních. Middleware funguje jako backstop pro přístup k databázi mimo zdobená zobrazení, jako je správce, signály nebo jiný middleware. Dekorátor @retry_on_transient dává autorům zobrazení jemnější kontrolu nad tím, které operace se mají opakovat. Pokud přechodná chyba unikne dekorátoru, middleware opakuje celý požadavek, takže nejhorší případ je až devět pokusů, než se klientovi zobrazí chyba. Pokud je tento strop pro váš rozpočet latence příliš vysoký, uberte jednu vrstvu nebo snižte max_retries u vrstvy, kterou ponecháte.

Další informace o každé části této konfigurace najdete v tématu Referenční informace ke konfiguraci, Možnosti připojení, Sdružování připojení, Logika opakování a odolnost připojení a ověřování Microsoft Entra.

Klíčové funkce

  • Zásuvný backend pro Django: Nastavte ENGINE na "mssql" a ORM Djanga, migrace, administrace a příkazy pro správu budou fungovat nad SQL Serverem.
  • Postaveno na ovladači pyodbc a ODBC 18: Připojení šifrovaná protokolem TLS ve výchozím nastavení a široká podpora platformy v systémech Windows, Linux a macOS.
  • Široká matice verzí: Django 3.2 až 6.0, Python 3.8 až 3.14 a SQL Server 2016 až 2025.
  • ověřování Microsoft Entra ID: Připojení bez hesla pomocí spravované identity, instančního objektu služby a interaktivních a integrovaných postupů prostřednictvím extra_params.
  • Migrace Django: Migrace schématu do SQL Server, včetně typů sloupců specifických pro SQL Server.
  • Podpora JSONField: Nativní JSONField s podporou úložiště nvarchar(max) a vyhledávání v Django.
  • Always Encrypted: Šifrování na straně klienta pro citlivé sloupce
  • Hromadné operace: bulk_create a bulk_update vůči serveru SQL Server s přiměřenými velikostmi dávek.
  • Přechodné opakování: Integrované zpracování běžných Azure SQL přechodných chyb během připojení a provádění dotazů.
  • inspectdb: Generování modelů Django z existujících schémat SQL Server.

Začínáme

Article Description
Installation Nainstalujte mssql-django a ovladač Microsoft ODBC pro SQL Server.
Rychlý start: Připojení Django k SQL Server Připojte projekt Django k SQL Server a spusťte první migraci.

Konfigurace a připojení

Article Description
Referenční informace ke konfiguraci Úplný odkaz na slovník Django DATABASES s mssql-django.
Možnosti připojení OPTIONS, extra_params, časové limity a konfigurace ovladače ODBC.
Sdružování připojení CONN_MAX_AGE, CONN_HEALTH_CHECKS a integrace externího fondu.
Logika opakování a odolnost připojení Detekujte přechodné chyby a opakujte připojení a dotazy.
Ověřování Microsoft Entra Ověřování bez hesla se spravovanou identitou, instančním objektem, interaktivními a integrovanými toky
Osvědčené postupy zabezpečení Parametrizace, správa tajných kódů, nejnižší oprávnění a šifrování.
Always Encrypted Nakonfigurujte šifrování na straně klienta pro citlivé sloupce.

Modely, migrace a datové typy

Article Description
Migrace databází Spusťte migrace Django na SQL Server, včetně typů sloupců specifických pro SQL Server.
Pole Django pro mapování typů SQL Server Jak se pole modelu Django mapují na datové typy v SQL Serveru.
Podpora JSONField Použijte JSONField s dotazy v SQL Serveru a Djangu.
Modely zpětné analýzy s využitím inspectdb Vygenerujte modely Django z existujících schémat SQL Server.
Podpora časových pásem USE_TZ, datetimeoffset a datumy a časy s podporou časového pásma.

Dotazování a práce s daty

Article Description
Hromadné operace bulk_create, bulk_update a ladění velikosti dávky.
Správa transakcí atomic, úrovně izolace, body obnovení a řešení uváznutí.
Nezpracované dotazy SQL RawSQL, connection.cursor() a syntaxe specifická pro SQL Server.
Uložené procedury Volejte uložené procedury SQL Serveru z Django.

Nasazení, testování a ladění

Article Description
Nasadit do služby Azure App Service Odešlete web Django do Azure App Service pomocí mssql-django.
Kontejner a místní vývoj Kontejnery Dockeru, devcontainery a kanály CI pro Django + SQL Server.
Testování Spusťte testovací sady Django na SQL Server.
Ladění výkonu Indexy, vzory dotazů, znovupoužití připojení a velikosti dávek.
Troubleshooting Běžné chyby, diagnostika ODBC a protokolování

Přechod na mssql-django

Article Description
Migrace z django-mssql-back-endu Přejděte z komunitního django-mssql-backend balíčku na mssql-django.
Migrace z jiných databází Přesuňte projekt Django z jiného back-endu databáze do SQL Server.
Migrace z PostgreSQL Průvodce jedním zastavením pro vývojáře Django, kteří přecházejí z PostgreSQL na SQL Server.
Article Description
Životní cyklus podpory Podporované verze Django, Python a SQL Server.
Co je nového Historie verzí a hlavní body vydání.
Omezení a nepodporované funkce v mssql-django Omezení back-endu a nepodporované funkce
Nejčastější dotazy Nejčastější dotazy