Cómo conectar Django con Azure SQL

Cómo conectar Django con Azure SQL

Nov 22, 2025

usando una vista (View) sobre AdventureWorks
Encuentra el codigo completo aca

https://github.com/joseantcloud/paas-condjango-sql-azure

¿Alguna vez quisiste leer datos reales de SQL Server / Azure SQL desde Django, pero sin pelearte con todas las tablas del demo de Microsoft?
En este mini–proyecto vas a ver cómo hacerlo de forma limpia usando algo muy poderoso que quizá tengas medio olvidado: las vistas (views) en SQL Server.

La idea es simple:

  • Tenés la base xdemo en Azure SQL con las tablas de SalesLT (el clásico demo tipo AdventureWorks).

  • De ahí tomamos la tabla SalesLT.Product.

  • Creamos una vista llamada dbo.ProductView con sólo las columnas que nos interesan.

  • Django se conecta a Azure SQL, pero en vez de apuntar directo a la tabla, apunta a la vista.

  • Y al final exponemos un endpoint /products/ que devuelve un JSON con los productos.

Es como ponerle unos lentes a Django: en lugar de ver todo el desorden de la base, ve una vista limpia y filtrada para consumir.

Primero: ¿qué es una vista (View) en SQL Server?

Una vista es básicamente un SELECT guardado con nombre.
No es una tabla física nueva; es más bien una ventana lógica sobre una o varias tablas.

image

Cuando vos escribís:


SELECT * FROM dbo.ProductView;

SQL Server por dentro hace algo como:

SELECT
    P.ProductID,
    P.Name,
    P.ProductNumber
FROM SalesLT.Product AS P;

La magia es que:

  • Podés esconder columnas que no querés mostrar.

  • Podés pre–filtrar datos (por ejemplo, sólo productos activos).

  • Podés estandarizar una consulta “oficial” que varios sistemas reúsan.

  • Y para Django, esa vista se ve igual que una tabla a la hora de hacer SELECT.

En pocas palabras: vos le das a Django una vista y él se porta como si fuera una tabla más.

Configurando Django para conectarse a Azure SQL

Crear la carpeta del proyecto y el entorno virtual

Abrí cmd (o PowerShell) en la carpeta donde querés tu proyecto, y ejecutá:

mkdir django-azure-products
cd django-azure-products

python -m venv .venv

REM Activar entorno en cmd:
.venv\Scripts\activate

REM (En PowerShell sería:)
REM .venv\Scripts\Activate.ps1

¿Qué estás haciendo acá?

  • Creás una carpeta para este proyecto, para no mezclar cosas con otros experimentos.

  • python -m venv .venv crea un entorno virtual: es como una “cajita” donde instalás librerías sin ensuciar el Python global.

  • Cuando ves algo como (.venv) antes del prompt, sabés que todo lo que instalés va a ese entorno y no afecta al resto del sistema.

Instalar Django y el backend para SQL Server

Con el entorno activo, instalás lo que vas a usar:

pip install django mssql-django pyodbc

Podés guardar las dependencias en un archivo (no es obligatorio, pero queda bien bonito):

pip freeze > requirements.txt

Crear el proyecto Django:

django-admin startproject myproject .

Crear la app donde vas a manejar los productos

>python manage.py startapp store

es importante lo siguiente, porque en el video lo deje de ultimo y casi daña todo el proyecto

Ahora hay que decirle a Django que esta app existe.
Abrí myproject/settings.py y agregá 'store', en INSTALLED_APPS:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # acá registrás tu app
    'store',
]

Sin esto, Django ni se entera que store existe. Es como invitarla a la fiesta

Configurar la base de datos Azure SQL en settings.py

puedes generar una contraseña segura desde aca

https://generatorx.netlify.app/

DATABASES = {
    "default": {
        # Vos le decís a Django: "Usá el backend de SQL Server"
        "ENGINE": "mssql",

        # Nombre de la base donde está SalesLT.Product y la vista dbo.ProductView
        "NAME": "elname",

        # Usuario y contraseña de tu Azure SQL
        "USER": "eluser",
        "PASSWORD": "elpassword**",

        # Servidor y puerto de Azure SQL
        "HOST": "elserver.database.windows.net",
        "PORT": "1433",

        "OPTIONS": {
            # El driver ODBC instalado en tu máquina (chequealo en ODBC Data Sources)
            "driver": "ODBC Driver 17 for SQL Server",

            # Azure recomienda cifrar la conexión
            "encrypt": True,

            # Más seguro dejarlo en False (no confiar ciegamente en el certificado)
            "trustServerCertificate": False,
        },
    }
}

¿Qué pasa internamente con esto?

Cuando más adelante hagas algo como Product.objects.all():

  1. Django ve que ENGINE es "mssql".

  2. Usa el backend mssql-django para generar SQL compatible con SQL Server.

  3. Ese SQL se manda a xdemo en xdemox.database.windows.net usando pyodbc + ODBC Driver 17.

  4. Azure SQL ejecuta la consulta y devuelve filas.

  5. Django las convierte en instancias de tu modelo Product.

Todo eso, vos lo disparás con una línea de código… bastante loco si lo pensás así

Crear el modelo Product que apunta a la vista ProductView

Ahora corresponde enseñarle a Django cómo luce cada fila de tu vista dbo.ProductView.
Abrí store/models.py y poné:

from django.db import models

class Product(models.Model):
    # Este campo representa la columna ProductID de la vista.
    # Lo ponés como primary_key para que Django sepa identificar cada producto.
    productid = models.IntegerField(
        db_column="ProductID",
        primary_key=True
    )

    # Columna Name → nombre del producto (texto corto)
    name = models.CharField(
        db_column="Name",
        max_length=50,
    )

    # Columna ProductNumber → código del producto
    productnumber = models.CharField(
        db_column="ProductNumber",
        max_length=50,
    )

    class Meta:
        # Te explico esta parte con mananzas: le decís a Django:
        # "Esta tabla/vista NO la manejes vos con migrations;
        #  ya existe en la base, sólo quiero leerla."
        managed = False

        # Nombre real de la vista en la base.
        # Como la creaste como dbo.ProductView, la referenciás así, 
        # por eso iba copiando todo en el sticky notes, te recordas?
        db_table = "dbo.ProductView"

    def __str__(self):
        # Representación amigable para consola/admin.
        return f"{self.name} ({self.productnumber})"

¿Por qué funciona esto?

  • Para Django, cada clase que hereda de models.Model es un modelo: una especie de plantilla de cómo luce una fila.

  • db_column actúa como traductor entre el nombre que vos usás en Python (productid) y el nombre real en SQL (ProductID).

  • db_table = "dbo.ProductView" le dice a Django dónde ir a buscar esos datos.

  • managed = False evita que Django diga “ah, no existe ProductView, la creo yo”: vos ya la creaste a mano en SQL, y además es una vista.

Crear la vista Django product_list para devolver JSON

Ahora toca escribir la lógica que se ejecuta cuando alguien visite /products/.
Abrí store/views.py y agregá:

from django.http import JsonResponse
from .models import Product

def product_list(request):
    # 1) Pedís todos los productos a través del ORM.
    #    Esto se traduce en un SELECT sobre dbo.ProductView.
    queryset = Product.objects.all()

    # 2) Limitás por si acaso, para no traer miles de filas de golpe.
    products = queryset[:100]

    # 3) Convertís cada Product en un diccionario nativo de Python.
    data = []
    for p in products:
        data.append({
            "ProductID": p.productid,
            "Name": p.name,
            "ProductNumber": p.productnumber,
        })

    # 4) Devolvés un JSON.
    #    safe=False indica que está bien devolver una lista como raíz del JSON.
    return JsonResponse(data, safe=False)

¿Qué consulta dispara esto realmente?

La combinación Product.objects.all()[:100] contra db_table = "dbo.ProductView" termina siendo algo muy parecido a:

SELECT TOP (100)
    [ProductID],
    [Name],
    [ProductNumber]
FROM [dbo].[ProductView];

Y recordá: ProductView por dentro lee SalesLT.Product.
Así que tu flujo es:

Django --> modelo Product ---> vista dbo.ProductView ---> tabla SalesLT.Product.

Conectar todo con una URL

image

Falta el último cable: la ruta HTTP que apunta a esta función.

Abrí myproject/urls.py y dejalo así:

from django.contrib import admin
from django.urls import path
from store.views import product_list

urlpatterns = [
    path('admin/', admin.site.urls),

    # Cuando visites /products/, Django va a ejecutar product_list()
    path('products/', product_list, name='product-list'),
]

veamos si funcionó:

En la consola (con el entorno todavía activo):

python manage.py check


Si no hay errores, levantás el servidor:

python manage.py runserver


Ahora abrís el navegador y vas a:

http://127.0.0.1:8000/products/

image

Recuerda que esta es la explicación de el video relacionado con este proyecto.

Apoyame para comprar el libro:

https://a.co/d/4RuKl3C

Vous aimez cette publication ?

Achetez un livre à Ant Cloud | Microsoft Full-Stack

Plus de Ant Cloud | Microsoft Full-Stack