Guía Esencial del Framework Django

Django es un framwork web de alto nivel escrito en Python que fomenta el desarrollo rápido y el diseño limpio y pragmático. Creado por desarrolladores experimentados, se encarga de gran parte de las molestias del desarrollo web, permitiéndote concentrarte en escribir tu aplicación sin tener que reinventar la rueda. Es de código abierto y cuenta con una comunidad próspera y activa.

Arquitectura y Componentes Principales de un Proyecto Django

Un proyecto Django típicamente se estructura en varias aplicaciones reutilizables. Cada aplicación maneja una funcionalidad específica (como un blog, un sistema de autenticación o una tienda en línea). La estructura de directorios de un proyecto base incluye:

  • Directorio del proyecto: Contiene la configuración global (settings.py), la definición de URL raíz (urls.py) y el servidor WSGI (wsgi.py).
  • Archivos de gestión: manage.py es una utilidad de línea de comandos para interactuar con el proyecto (servidor de desarrollo, migraciones, etc.).
  • Aplicaciones: Cada aplicación tiene su propio directorio con archivos como:
    • models.py: Define la estructura de la base de datos usando el ORM de Django.
    • views.py: Contiene la lógica de negocio para manejar peticiones HTTP.
    • urls.py: Encamina URLs específicas de la aplicación a sus vistas correspondientes.
  • Directorios de recursos: templates/ para archivos HTML con sintaxis de plantillas y static/ para archivos estáticos (CSS, JavaScript, imágenes).

Configuración del Proyecto (settings.py)

Este archivo es el corazón de la configuración. A continuación, algunos ajustes clave:

Aplicaciones instaladas


INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'mi_aplicacion.apps.MiAplicacionConfig',  # Forma recomendada
    # 'mi_aplicacion',  # Forma abreviada
]

Directorios de plantillas


import os
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'plantillas')],
        # ...
    },
]

Acceso a archivos estáticos

Los archivos estáticos requieren configuración para ser servidos:


# Prefijo de URL para acceder a los archivos estáticos
STATIC_URL = '/archivos_estaticos/'

# Rutas de directorios donde se almacenan los archivos estáticos adicionales
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'recursos_comunes'),
]

En las plantillas, se cargan usando la etiqueta {% load static %}:


{% load static %}
<link rel="stylesheet" href="{% static 'css/estilos.css' %}">

Sistema de Enrutamiento (URL Dispatch)

Django utiliza una lista de patrones de URL definidos en urls.py para mapear solicitudes a funciones o clases de vista.

Definición básica de rutas


from django.urls import path
from . import vistas

urlpatterns = [
    path('', vistas.pagina_inicio, name='inicio'),
    path('articulos/<int:articulo_id>/', vistas.detalle_articulo, name='detalle_articulo'),
    path('buscar/<str:termino>/', vistas.resultados_busqueda),
]

Convertidores de ruta

Permiten capturar valores de la URL y pasarlos a la vista. Ejemplos: <int:pk>, <str:nombre>, <slug:enlace>.

Resolución inversa y espacios de nombres

La resolución inversa genera URLs a partir de su nombre, evitando URLs codificadas:


# En el código Python (vista)
from django.urls import reverse
url = reverse('detalle_articulo', args=[42])

# En la plantilla HTML
<a href="{% url 'detalle_articulo' articulo_id=42 %}">Ver</a>

Para aplicaciones con URLs con el mismo nombre, se usan espacios de nombres:


# urls.py raíz
from django.urls import include, path
urlpatterns = [
    path('noticias/', include(('noticias.urls', 'noticias'), namespace='noticias')),
]

# En la plantilla
<a href="{% url 'noticias:detalle' noticia.id %}">{# ... #}</a>

Capa de Vistas

Las vistas reciben una petición HTTP y devuelven una respuesta. Pueden ser funciones (FBV) o clases (CBV).

Funciones de Vista (FBV)


from django.http import HttpResponse, JsonResponse
from django.shortcuts import render, redirect

def mi_vista_funcional(request):
    if request.method == 'POST':
        # Procesar datos POST
        nombre = request.POST.get('nombre')
        return redirect('exito')
    # Para GET u otros métodos
    contexto = {'titulo': 'Mi Página'}
    return render(request, 'mi_plantilla.html', contexto)

def api_endpoint(request):
    datos = {'mensaje': 'OK', 'items': [1, 2, 3]}
    return JsonResponse(datos)

Clases de Vista (CBV)


from django.views import View
from django.http import HttpResponse

class MiVistaClase(View):
    def get(self, request, *args, **kwargs):
        return HttpResponse("Respuesta a GET")
    
    def post(self, request, *args, **kwargs):
        return HttpResponse("Respuesta a POST")

# En urls.py
urlpatterns = [
    path('clase/', MiVistaClase.as_view()),
]

El objeto Request

Proporciona información sobre la solicitud:

  • request.method: 'GET', 'POST', etc.
  • request.GET: Datos de la consulta (query string).
  • request.POST: Datos enviados via formulario POST.
  • request.FILES: Archivos subidos.

Motor de Plantillas

Las plantillas HTML pueden incluir una sintaxis especial para lógica y variables.

Renderización y contexto


# En la vista
def index(request):
    productos = Producto.objects.filter(disponible=True)
    return render(request, 'tienda/index.html', {'productos': productos})


<!-- En index.html -->
{% for prod in productos %}
    <div>{{ prod.nombre }} - {{ prod.precio|floatformat:2 }}</div>
{% empty %}
    <p>No hay productos disponibles.</p>
{% endfor %}

Filtros

Transforman variables: {{ valor|filtrar:argumento }}. Ejemplos: date, default, truncatewords, length.

Herencia y bloques


<!-- base.html -->

<html>
<head>
    <title>{% block titulo %}Sitio{% endblock %}</title>
</head>
<body>
    {% block contenido %}{% endblock %}
</body>
</html>

<!-- pagina.html -->
{% extends "base.html" %}
{% block titulo %}Mi Página{% endblock %}
{% block contenido %}
    <h1>Bienvenido</h1>
{% endblock %}

Sistema de Modelos (ORM)

El ORM mapea clases de Python a tablas de base de datos.

Definición de modelos


from django.db import models

class Departamento(models.Model):
    nombre = models.CharField(max_length=100)
    ubicacion = models.CharField(max_length=100, blank=True)

    def __str__(self):
        return self.nombre

class Empleado(models.Model):
    nombre_completo = models.CharField("Nombre", max_length=150)
    departamento = models.ForeignKey(
        Departamento,
        on_delete=models.CASCADE,
        related_name='empleados'
    )
    fecha_ingreso = models.DateField(auto_now_add=True)
    salario = models.DecimalField(max_digits=10, decimal_places=2)

    class Meta:
        ordering = ['fecha_ingreso']
        verbose_name_plural = 'Empleados'

Consultas y operaciones CRUD


# Crear
dep = Departamento.objects.create(nombre='Tecnología')

# Leer
todos = Empleado.objects.all()
techs = Empleado.objects.filter(departamento__nombre='Tecnología')
caros = Empleado.objects.filter(salario__gte=50000).order_by('-salario')
ultimo = Empleado.objects.latest('fecha_ingreso')

# Actualizar
Empleado.objects.filter(salario__lt=30000).update(salario=30000)

# Borrar
Empleado.objects.filter(activo=False).delete()

Relaciones

  • ForeignKey (muchos a uno): models.ForeignKey(OtroModelo, on_delete=models.CASCADE)
  • ManyToManyField: models.ManyToManyField(OtroModelo)
  • OneToOneField: models.OneToOneField(OtroModelo, on_delete=models.CASCADE)

Consultas relacionadas: Empleado.objects.select_related('departamento') (para FK) o Empleado.objects.prefetch_related('proyectos') (para M2M).

Consultas avanzadas (F y Q)


from django.db.models import F, Q

# Usar F() para referenciar campos en consultas
Empleado.objects.update(salario=F('salario') * 1.1)

# Usar Q() para consultas complejas
Empleado.objects.filter(
    Q(salario__gt=40000) | Q(departamento__nombre='Ventas'),
    activo=True
)

Agregación y Agrupación


from django.db.models import Avg, Count, Max

# Agregación sobre todo el queryset
Empleado.objects.aggregate(salario_promedio=Avg('salario'))

# Agrupación (GROUP BY)
EmpleadosPorDepto = Empleado.objects.values('departamento__nombre') \
    .annotate(
        num_empleados=Count('id'),
        salario_max=Max('salario')
    ) \
    .order_by('-num_empleados')

Migraciones

Sincronizan los cambios en los modelos con la base de datos:

  1. python manage.py makemigrations: Genera los archivos de migración.
  2. python manage.py migrate: Aplica las migraciones a la base de datos.
  3. python manage.py showmigrations: Lista el estado de las migraciones.

Etiquetas: Django Python ORM

Publicado el 6-11 21:02