Django es el framework web más popular y completo escrito en Python. Desarrollado originalmente para powering el periódico Lawrence Journal-World, hoy es utilizado por empresas como Instagram, Pinterest, Spotify y Dropbox para construir aplicaciones web robustas y escalables.

En esta guía completa, aprenderás todo lo que necesitas para empezar a desarrollar con Django, desde conceptos básicos hasta técnicas avanzadas que te convertirán en un desarrollador competente.

¿Qué es Django?

Django es un framework web de alto nivel escrito completamente en Python que sigue la filosofía de "baterías incluidas". Esto significa que ya viene con todo lo que necesitas para construir una aplicación web completa — desde autenticación hasta gestión de bases de datos, desde interfaz de administración hasta procesamiento de formularios.

La filosofía de Django está basada en algunos principios fundamentales que lo hacen único:

  • DRY (Don't Repeat Yourself): Django fomenta la reutilización de código a través de su arquitectura basada en aplicaciones
  • MTV (Model-Template-View): Un patrón de arquitectura claro que separa responsabilidades
  • Pragmatismo: El framework fue diseñado para ayudar a los desarrolladores a resolver problemas del mundo real rápidamente
  • Explícito es mejor que implícito: El código claro y legible es preferido sobre la "magia"

Según la documentación oficial de Django, el framework fue lanzado en 2005 y desde entonces ha sido mantenido por una comunidad activa de desarrolladores que contribuyen regularmente con mejoras y actualizaciones.

¿Por Qué Usar Django?

Existen muchas razones para elegir Django como tu framework web. Exploremos las principales ventajas que lo distinguen de otros frameworks de Python como Flask o FastAPI.

1. Baterías Incluidas

A diferencia de los frameworks ligeros, Django viene con un conjunto completo de características integradas que de otro modo requerirían bibliotecas y configuración adicionales. Esto incluye:

  • Sistema completo de autenticación de usuarios
  • Interfaz de administración automática (Django Admin)
  • Sistema de formularios con validación
  • Manejo de carga de archivos
  • Sistema de internacionalización (i18n)
  • Protección contra vulnerabilidades comunes (CSRF, XSS, SQL Injection)

Según Real Python, el enfoque de "baterías incluidas" significa que puedes enfocarte en lo que realmente importa: construir las funcionalidades únicas de tu aplicación, no reinventar la rueda.

2. ORM Potente

El ORM de Django (Object-Relational Mapper) es una de sus características más potentes, permitiéndote interactuar con bases de datos usando objetos Python en lugar de escribir SQL manualmente. Esto proporciona varios beneficios:

from django.db import models

class Producto(models.Model):
    nombre = models.CharField(max_length=200)
    precio = models.DecimalField(max_digits=10, decimal_places=2)
    descripcion = models.TextField()
    fecha_creacion = models.DateTimeField(auto_now_add=True)
    categoria = models.ForeignKey('Categoria', on_delete=models.CASCADE)

    class Meta:
        ordering = ['-fecha_creacion']

    def __str__(self):
        return self.nombre

Con el ORM, puedes realizar operaciones complejas de base de datos sin escribir una sola línea de SQL:

# Crear un producto
producto = Producto.objects.create(
    nombre="Notebook Python",
    precio=3500.00,
    descripcion="Perfecto para desarrolladores",
    categoria=categoria
)

# Buscar productos con filtros avanzados
productos = Producto.objects.filter(
    precio__lte=5000
).filter(
    categoria__nombre__contains="Electrónicos"
).order_by('-precio')

# Agregaciones
from django.db.models import Avg, Count
precios_promedio = Producto.objects.aggregate(Avg('precio'))

Según la Documentación de Django, el ORM soporta múltiples backends de base de datos incluyendo PostgreSQL, MySQL, SQLite y Oracle.

3. Django Admin

Una de las características más impresionantes de Django es la interfaz de Admin generada automáticamente. En minutos, puedes tener un panel de administración completamente funcional para gestionar tus datos.

# models.py
from django.db import models

class Articulo(models.Model):
    titulo = models.CharField(max_length=200)
    contenido = models.TextField()
    publicado = models.BooleanField(default=False)
    fecha_publicacion = models.DateTimeField()

    def __str__(self):
        return self.titulo

# admin.py
from django.contrib import admin
from .models import Articulo

@admin.register(Articulo)
class ArticuloAdmin(admin.ModelAdmin):
    list_display = ['titulo', 'publicado', 'fecha_publicacion']
    list_filter = ['publicado', 'fecha_publicacion']
    search_fields = ['titulo', 'contenido']
    date_hierarchy = 'fecha_publicacion'

Con solo estas pocas líneas, tendrás un admin donde puedes listar, filtrar, buscar, editar y crear artículos. Django Admin también soporta edición en línea, acciones masivas y mucho más.

4. Seguridad

Django fue diseñado pensando en la seguridad, protegiendo tus aplicaciones contra vulnerabilidades comunes por defecto. Según OWASP, Django incluye protección integrada contra:

  • SQL Injection: Las consultas parametrizadas previenen ataques de inyección SQL
  • Cross-Site Scripting (XSS): El auto-escapado de plantillas protege contra XSS
  • Cross-Site Request Forgery (CSRF): Los tokens CSRF se incluyen automáticamente en los formularios
  • Clickjacking: El middleware X-Frame-Options previene clickjacking
  • Almacenamiento de Contraseñas: Hashing seguro de contraseñas con PBKDF2 por defecto

5. Comunidad y Ecosistema

Con más de 15 años de existencia, Django tiene una comunidad masiva y un rico ecosistema de paquetes. Puedes encontrar paquetes para prácticamente cualquier funcionalidad que necesites, desde envío de SMS hasta procesamiento de pagos.

Según PyPI, existen miles de paquetes de Django disponibles, cubriendo áreas como:

  • Autenticación (django-allauth, django-rest-auth)
  • APIs (Django REST Framework, GraphQL)
  • Temas de Admin (django-jet, django-grappelli)
  • E-commerce (django-oscar, saleor)
  • CMS (Wagtail, django-cms)

Instalando Django

Comenzar con Django es muy sencillo. Puedes instalar usando pip:

# Crear entorno virtual (recomendado)
python -m venv venv
source venv/bin/activate  # Linux/Mac
venv\Scripts\activate  # Windows

# Instalar Django
pip install django

# Verificar instalación
django-admin --version

Alternativamente, puedes crear un nuevo proyecto Django usando django-admin:

django-admin startproject myproject
cd myproject
python manage.py runserver

Esto creará una estructura básica de proyecto Django. Según Python.org, es muy recomendable usar entornos virtuales para aislar tus proyectos Django y evitar conflictos de dependencias.

Entendiendo la Estructura de Django

Un proyecto Django está organizado en una estructura jerárquica que puede parecer compleja al principio, pero tiene perfecto sentido una vez que entiendes cómo las piezas se unen.

Proyectos vs Aplicaciones

Es crucial entender la diferencia entre proyecto y aplicación en Django:

  • Proyecto: Toda la configuración de la aplicación. Es el contenedor que contiene todas las configuraciones de tu sitio
  • Aplicación: Un componente reutilizable que realiza una funcionalidad específica. Puede ser reutilizado en diferentes proyectos

Por ejemplo, un proyecto de e-commerce podría tener aplicaciones como "catálogo", "carrito", "pedidos" y "pagos".

# Crear una aplicación
python manage.py startapp blog

Arquitectura MTV

Django sigue el patrón Model-Template-View (MTV), que es similar a MVC pero con responsabilidades ligeramente diferentes:

  • Model: Define la estructura de los datos e interactúa con la base de datos
  • Template: Responsible de la capa de presentación (HTML)
  • View: Contiene la lógica de negocio y procesa solicitudes

Según MDN Web Docs, esta Separación de Responsabilidades hace que el código sea más mantenible y testeable.

Creando Tu Primera Aplicación Django

Vamos a crear una aplicación de blog simple para demostrar los conceptos fundamentales de Django. Este ejemplo cubrirá modelos, vistas, URLs y plantillas.

Paso 1: Configurar la Base de Datos

Django usa SQLite por defecto, que es perfecto para desarrollo. Para configurar, necesitas ejecutar las migraciones:

python manage.py migrate

Esto creará todas las tablas de base de datos necesarias, incluyendo las de usuarios, sesiones y autenticación. También puedes personalizar tu base de datos editando settings.py:

# settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydb',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

Según W3Schools, PostgreSQL es muy recomendado para entornos de producción debido a su robustez y escalabilidad.

Paso 2: Crear Modelos

Los modelos son la base de tu aplicación Django. Creemos un modelo de blog simple:

# blog/models.py
from django.db import models
from django.contrib.auth.models import User

class Categoria(models.Model):
    nombre = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    descripcion = models.TextField(blank=True)

    class Meta:
        verbose_name_plural = "Categorías"

    def __str__(self):
        return self.nombre

class Post(models.Model):
    titulo = models.CharField(max_length=200)
    slug = models.SlugField(unique=True)
    contenido = models.TextField()
    autor = models.ForeignKey(User, on_delete=models.CASCADE)
    categoria = models.ForeignKey(Categoria, on_delete=models.SET_NULL, null=True)
    creado_en = models.DateTimeField(auto_now_add=True)
    actualizado_en = models.DateTimeField(auto_now=True)
    publicado = models.BooleanField(default=False)

    class Meta:
        ordering = ['-creado_en']

    def __str__(self):
        return self.titulo

Después de crear tus modelos, necesitas crear las migraciones:

python manage.py makemigrations
python manage.py migrate

Paso 3: Crear Vistas

Las vistas son donde vive la lógica de la aplicación. Django soporta tanto vistas basadas en funciones (FBV) como vistas basadas en clases (CBV):

# blog/views.py
from django.shortcuts import render, get_object_or_404
from django.views.generic import ListView, DetailView
from django.models import Post
from .models import Categoria

class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'
    paginate_by = 10

    def get_queryset(self):
        return Post.objects.filter(publicado=True)

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'
    context_object_name = 'post'

def posts_por_categoria(request, slug):
    categoria = get_object_or_404(Categoria, slug=slug)
    posts = Post.objects.filter(publicado=True, categoria=categoria)
    return render(request, 'blog/post_list.html', {
        'posts': posts,
        'categoria': categoria
    })

Paso 4: Configurar URLs

La configuración de URLs es donde mapeas URLs a vistas:

# blog/urls.py
from django.urls import path
from .views import PostListView, PostDetailView, posts_por_categoria

urlpatterns = [
    path('', PostListView.as_view(), name='post_list'),
    path('post/<slug:slug>/', PostDetailView.as_view(), name='post_detail'),
    path('categoria/<slug:slug>/', posts_por_categoria, name='posts_por_categoria'),
]

# myproject/urls.py (principal)
from django.contrib import admin
from django.urls import path, include

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

Paso 5: Crear Plantillas

Las plantillas son donde defines el HTML que será renderizado. El lenguaje de plantillas de Django es potente pero fácil de aprender:

<!-- templates/blog/post_list.html -->
{% extends 'base.html' %}

{% block content %}
<h1>Blog</h1>

{% for post in posts %}
<article class="post-card">
    <h2><a href="{% url 'post_detail' post.slug %}">{{ post.titulo }}</a></h2>
    <p class="meta">
        Por {{ post.autor.username }} el {{ post.creado_en|date:"d/m/Y" }}
    </p>
    <p>{{ post.contenido|truncatewords:50 }}</p>
    <a href="{% url 'post_detail' post.slug %}">Leer más...</a>
</article>
{% empty %}
<p>No se encontraron posts.</p>
{% endfor %}

{% if page_obj.has_other_pages %}
<div class="pagination">
    {% if page_obj.has_previous %}
    <a href="?page={{ page_obj.previous_page_number }}">Anterior</a>
    {% endif %}
    <span>Página {{ page_obj.number }} de {{ page_obj.paginator.num_pages }}</span>
    {% if page_obj.has_next %}
    <a href="?page={{ page_obj.next_page_number }}">Siguiente</a>
    {% endif %}
</div>
{% endif %}
{% endblock %}

Django REST Framework

Para crear APIs RESTful con Django, Django REST Framework (DRF) es la opción más popular. Extiende la funcionalidad de Django para hacer la construcción de APIs muy sencilla.

# requirements.txt
djangorestframework>=3.14.0

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
]

# serializers.py
from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    autor = serializers.StringRelatedField()
    categoria = serializers.StringRelatedField()

    class Meta:
        model = Post
        fields = ['id', 'titulo', 'slug', 'contenido', 'autor', 'categoria', 'creado_en']

# views.py
from rest_framework import viewsets
from rest_framework.permissions import IsAuthenticatedOrReadOnly
from .models import Post
from .serializers import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.filter(publicado=True)
    serializer_class = PostSerializer
    permission_classes = [IsAuthenticatedOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(autor=self.request.user)

# urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import PostViewSet

router = DefaultRouter()
router.register(r'posts', PostViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
]

Según la documentación de Django REST Framework, DRF proporciona características como autenticación, serialización, validación y viewsets que hacen la construcción de APIs mucho más fácil.

Autenticación y Autorización

Django tiene un sistema de autenticación integrado que maneja usuarios, grupos, permisos y sesiones. Exploremos cómo usarlo efectivamente.

Creando un Sistema de Login

# views.py
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from django.shortcuts import render, redirect

def login_view(request):
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(request, username=username, password=password)
        if user is not None:
            login(request, user)
            return redirect('home')
        else:
            return render(request, 'login.html', {'error': 'Credenciales inválidas'})
    return render(request, 'login.html')

@login_required
def profile_view(request):
    return render(request, 'profile.html', {'user': request.user})

def logout_view(request):
    logout(request)
    return redirect('home')
<!-- templates/registration/login.html -->
<form method="post">
    {% csrf_token %}
    <input type="text" name="username" placeholder="Usuario" required>
    <input type="password" name="password" placeholder="Contraseña" required>
    <button type="submit">Iniciar Sesión</button>
</form>

Permisos Personalizados

Puedes crear permisos personalizados para controlar el acceso a las vistas:

from rest_framework import permissions

class IsOwnerOrReadOnly(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        if request.method in permissions.SAFE_METHODS:
            return True
        return obj.autor == request.user or request.user.is_staff

Probando Aplicaciones Django

Las pruebas son esenciales para mantener código de calidad. Django proporciona un marco de pruebas potente integrado con unittest.

# blog/tests.py
from django.test import TestCase
from django.contrib.auth.models import User
from .models import Post, Categoria
from django.utils import timezone
from django.test import Client

class PostModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(
            username='testuser',
            password='testpass123'
        )
        self.categoria = Categoria.objects.create(
            nombre='Tecnología',
            slug='tecnologia'
        )

    def test_creacion_post(self):
        post = Post.objects.create(
            titulo='Test Post',
            slug='test-post',
            contenido='Contenido de prueba',
            autor=self.user,
            categoria=self.categoria,
            publicado=True
        )
        self.assertEqual(post.__str__(), 'Test Post')
        self.assertTrue(post.publicado)

class PostViewTest(TestCase):
    def setUp(self):
        self.client = Client()

    def test_vista_lista_posts(self):
        response = self.client.get('/blog/')
        self.assertEqual(response.status_code, 200)

Para ejecutar las pruebas:

python manage.py test

Según la Documentación de Pruebas de Django, es una mejor práctica escribir pruebas para toda la funcionalidad crítica de tu aplicación.

Despliegue

Cuando tu aplicación está lista para producción, hay varias opciones de despliegue. Cubramos las más populares.

Usando Gunicorn

Gunicorn es un servidor HTTP WSGI ampliamente usado con Django:

pip install gunicorn

# Ejecutar con Gunicorn
gunicorn myproject.wsgi:application --bind 0.0.0.0:8000

Docker

Contenerizar tu aplicación Django con Docker es muy recomendado:

# Dockerfile
FROM python:3.11-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["gunicorn", "myproject.wsgi:application", "--bind", "0.0.0.0:8000"]
# docker-compose.yml
version: '3.8'

services:
  web:
    build: .
    ports:
      - "8000:8000"
    environment:
      - DEBUG=0
      - ALLOWED_HOSTS=tusitio.com
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      - POSTGRES_DB=mydb
      - POSTGRES_USER=myuser
      - POSTGRES_PASSWORD=mypassword
    volumes:
      - pgdata:/var/lib/postgresql/data

Plataformas de Hosting

Hay varias plataformas donde puedes desplegar tu aplicación Django:

  • Render: Despliegue fácil, buen nivel gratuito
  • Railway: Moderno, fácil de usar
  • Heroku: Opción clásica, ahora de pago
  • DigitalOcean: Control VPS, excelente para autoalojamiento

Según Stack Overflow, la elección de la plataforma depende de tus necesidades específicas como presupuesto, requisitos de escalabilidad y experiencia técnica.

Django vs Otros Frameworks

Es importante entender cuándo usar Django versus otros frameworks de Python. Aquí hay una comparación rápida:

  • vs Flask: Django es más de "baterías incluidas", mejor para aplicaciones grandes. Flask es más ligero, mejor para proyectos pequeños o microservicios
  • vs FastAPI: FastAPI es más rápido y mejor para APIs. Django es mejor para aplicaciones full-stack con plantillas
  • vs Pyramid: Pyramid es más flexible, Django es más opinionado con decisiones de diseño ya tomadas

Para aplicaciones web tradicionales que necesitan autenticación, admin e interacción con base de datos, Django generalmente es la mejor opción.

Próximos Pasos

Ahora que has aprendido los fundamentos de Django, aquí hay algunos pasos siguientes para continuar tu aprendizaje:

  • FastAPI Python — explora otro framework popular para APIs
  • Python Requests — aprende a hacer solicitudes HTTP
  • Practica creando tus propios proyectos
  • Explora paquetes como django-allauth para autenticación social
  • Aprende sobre caché con Redis
  • Explora Django Channels para WebSockets

Django es una habilidad valiosa para cualquier desarrollador de Python. Con esta guía, tienes una base sólida para empezar a construir tus propias aplicaciones web profesionales. ¡Sigue practicando y explorando la documentación oficial para convertirte en un experto!