6. Django Admin Profesional y Vistas CRUD ⚙️
1. La Metodología Pedagógica: De "Admin Ciego" a Panel SaaS
Uno de los mayores superpoderes de Django frente a otros frameworks backend es supanel de administración automático (django.contrib.admin). Lee los metadatos del ORM y genera al instante una interfaz web completa para crear, buscar, filtrar y auditar registros.
⚠️ El Problema de la Enseñanza Clásica: "El Admin Ciego"
La mayoría de cursos enseñan únicamente: admin.site.register(Vehiculo). El resultado es desastroso para el estudiante: ve una lista gris con nombres comoVehiculo object (1), sin buscador, sin filtros, y sin poder distinguir qué auto está disponible o en reparación. Esto hace que muchos piensen erróneamente que Django Admin es un "juguete obsoleto".
1.1 Creación del Superusuario
Para ingresar al panel de administración necesitas una cuenta con privilegios de superusuario (is_superuser = True). Ejecuta en tu terminal con el entorno virtual (venv) activo:
1.2 Las 6 Palancas de ModelAdmin: La Escalera de Producción
Para transformar el admin en una herramienta empresarial que cualquier departamento de operaciones pueda usar para gestionar miles de registros, aplicamos las 6 palancas de ModelAdmin:
Reemplaza los objetos crudos por tablas con columnas claras: Patente, Marca, Modelo y datos formateados.
Convierte estados de texto en etiquetas visuales con colores (Verde = Disponible, Rojo = En Taller).
Habilita búsqueda instantánea en campos directos y relaciones con claves foráneas (piloto__nombre).
Crea un panel lateral facetado con conteos automáticos por estado, tipo de vehículo o rangos de fecha.
Convierte celdas en inputs interactivos (estilo Excel/Google Sheets) para editar stock o estado sin entrar a cada ficha.
Patrón Maestro-Detalle (editar vehículo y sus revisiones técnicas en 1 sola pantalla) y acciones masivas en lote.
🧪 Laboratorio Interactivo: Prueba las 6 Palancas y el Rediseño con Unfold
Interactúa con los controles inferiores: activa cada nivel para observar cómo evoluciona la interfaz y pulsa el botón superior para alternar entre el diseño Django Clásico (2005) yDjango Unfold (Tailwind CSS 2026):
⚙️ Django Admin Studio:De "Admin Ciego" a Panel SaaS 2026
| Patente | Vehículo | Piloto Asignado | Estado | Kilometraje |
|---|---|---|---|---|
| FL-204-CL | Toyota Hilux 4x4 D-Cab CAMIONETA • 2023 | DISPONIBLE | 42,500 km | |
| VK-881-TX | Volvo FH16 750 Tracto CAMION • 2022 | EN_RUTA | 118,000 km | |
| MB-550-SP | Mercedes-Benz Sprinter 516 Maxi VAN • 2024 | MANTENIMIENTO | 18,400 km | |
| HY-309-AC | Hyundai Accent Prime 1.6 AUTO • 2021 | DISPONIBLE | 68,900 km | |
| SC-910-XT | Scania R500 Super V8 CAMION • 2023 | EN_RUTA | 89,300 km | |
| CH-774-DM | Chevrolet D-Max 3.0 4x4 CAMIONETA • 2022 | MANTENIMIENTO | 54,100 km |
# flota/admin.py (Django Unfold - Nivel 2: ModelAdmin Avanzado)
from django.contrib import admin
from django.utils.html import format_html
from unfold.admin import ModelAdmin, TabularInline
from unfold.decorators import action, display
from .models import Vehiculo, Mantenimiento, Piloto
@admin.register(Vehiculo)
class VehiculoAdmin(ModelAdmin):
# 1. Configuración de Unfold
warn_unsaved_form = True
list_filter_submit = True
list_per_page = 15
# 2. Columnas en la tabla principal
list_display = [
"patente",
"marca_modelo",
"piloto_card",
"estado_badge",
"kilometraje_fmt",
]
@display(description="Vehículo")
def marca_modelo(self, obj):
return f"{obj.marca} {obj.modelo} ({obj.anio})"
@display(description="Piloto Asignado")
def piloto_card(self, obj):
if not obj.piloto:
return "Sin Asignar"
return format_html(
'<div class="flex items-center gap-2">'
'<img src="{}" class="w-6 h-6 rounded-full"/>'
'<span>{}</span></div>',
obj.piloto.avatar.url, obj.piloto.nombre
)
@display(description="Estado Operativo", label=True)
def estado_badge(self, obj):
# Unfold renderiza automáticamente estilos modernos con labels
colores = {
"DISPONIBLE": "emerald",
"EN_RUTA": "blue",
"MANTENIMIENTO": "rose",
}
color = colores.get(obj.estado, "gray")
return obj.estado, color
1.3 Rediseño Visual Radical: De Django 2005 a Django Unfold (Tailwind CSS 2026)
Aunque ModelAdmin otorga funcionalidad completa, la estética por defecto de Django (diseñada a inicios de los 2000) luce anticuada para entregar a clientes o gerencias. En el ecosistema Python moderno existe un proyecto de código abierto que se ha convertido en el estándar indiscutible:django-unfold.
El tema más moderno del ecosistema: Soporte nativo de Modo Oscuro/Claro, tarjetas KPI de métricas en el Dashboard, gráficos con Chart.js, responsive real para celulares, y componentes visuales ricos (badges, progress bars, tabs).
Tema clásico basado en Bootstrap 4 y AdminLTE. Muy popular durante la última década con menú horizontal o lateral tradicional. Ideal si el resto de tu sitio ya utiliza Bootstrap.
Paso 1: Instalación y la "Regla de Oro" de settings.py
Para que Django cargue las plantillas modernas de Unfold antes que las plantillas por defecto del framework,"unfold" debe colocarse ANTES de "django.contrib.admin" en la lista INSTALLED_APPS:
Paso 2: Escribir admin.py con Unfold y Componentes Ricos
En tus archivos admin.py, en vez de heredar de admin.ModelAdmin, heredas deunfold.admin.ModelAdmin. Esto desbloquea decoradores visuales como @display(label=True)para badges automáticos y acciones estilizadas:
2. Arquitectura de Cada Vista CRUD (Create, Read, Update, Delete)
El acrónimo CRUD define las cuatro operaciones fundamentales sobre cualquier base de datos:
GET y procesa la carga de datos en base de datos mediante POST con validaciones de tipo e integridad.ListView) o en fichas individuales (DetailView).instance=obj), permite modificar sus atributos y aplica validaciones antes de guardar.POST para prevenir borrados accidentales y ejecuta obj.delete() con chequeo de integridad referencial.2.1 Formularios Basados en Modelos (ModelForm)
En Django, no escribes formularios HTML a mano. Utilizas forms.ModelForm, que genera los campos, etiquetas y validaciones directamente a partir de la definición de tu modelo:
2.2 Implementación de Cada Vista CRUD (FBV vs CBV)
A continuación comparamos cómo se implementan las 4 operaciones mediante funciones (FBV) y mediante clases genéricas (CBV):
⚡ Laboratorio Interactivo: Simulador de Django Admin y CRUD
Experimenta el ciclo de vida completo de un CRUD en tiempo real: crea registros pasando por las validaciones de clean(), busca y filtra como en Django Admin, edita instancias existentes y elimina elementos con confirmación.
Django Admin & CRUD Simulator
Experimenta el panel administrativo, formularios y ciclo Create-Read-Update-Delete
| ID | Título del Libro | Categoría | Precio Venta | Costo | Stock | Estado | Acciones CRUD | |
|---|---|---|---|---|---|---|---|---|
| #1 | Clean Code: Manual de desarrollo ágil | Ingeniería | $45.00 | $28.00 | 4 u. | ● Activo | ||
| #2 | Python Fluente 2da Edición | Backend | $65.00 | $42.00 | 2 u. | ● Activo | ||
| #3 | Django 5 Profesional | Backend | $55.00 | $34.00 | 6 u. | ● Activo | ||
| #4 | Patrones de Diseño (GoF) | Arquitectura | $50.00 | $30.00 | 0 u. | ○ Inactivo |
3. Ejercicios Didácticos: Proyecto 1 (Biblioteca)
Aplica las técnicas de administración y formularios sobre el dominio de la biblioteca.
Ejercicio 3.1: Formulario con Validación de Préstamos
Crea un ModelForm para SolicitudPrestamo que impida fijar una fecha de devolución superior a 30 días en el futuro.
Ver Solución Explicada
Ejercicio 3.2: Acción Personalizada en Django Admin con Mensajes
Escribe una acción en SolicitudPrestamoAdmin que permita seleccionar múltiples solicitudes atrasadas y condonar sus multas acumuladas poniéndolas en $0.00.
Ver Solución Explicada
4. Desafío Práctico: Segundo Proyecto — Tienda Online (`tienda`) 🛒
Implementa el panel administrativo y los formularios CRUD del segundo proyecto ubicado en C:\proyectos\django\tienda.
Reto 4.1: PedidoAdmin con TabularInline de Ítems y Acción de Despacho
En pedidos/admin.py, registra Pedido con una relación tabular de ItemPedidoInline para ver los productos comprados, cantidades y subtotales en la misma vista de administración. Añade una acción para marcar los pedidos seleccionados como 'ENVIADO'.
Ver Solución Explicada
Reto 4.2: ModelForm con Validación Cruzada (Precio vs Costo)
En catalogo/forms.py, crea ProductoForm garantizando que: 1. El SKU se guarde siempre en mayúsculas y tenga al menos 4 caracteres. 2. El precio de venta nunca sea inferior al costo de adquisición.
Ver Solución Explicada
Reto 4.3: Vista de Eliminación Suave (Soft Delete)
En comercio electrónico nunca se borra físicamente un producto si ya forma parte del historial de compras de clientes pasados (provocaría error de integridad referencial). Escribe una vista FBV desactivar_producto(request, pk) que al recibir un POST cambie disponible = False en vez de ejecutar delete().
Ver Solución Explicada
Ponte a prueba
Comprueba que dominas el panel de administración, la arquitectura CRUD y la validación de formularios en Django.


