Django es un marco web de Python que te permite lanzar una aplicación web lista para producción en días, no en meses. Escribes menos código repetitivo, obtienes un panel de administración listo para usar y despliegas en plataformas que soportan WSGI sin infraestructura personalizada. ¿Necesitas validar una idea rápidamente? Aquí está la clave: Django te lleva allí.
Foto: Ferenc Almasi en Unsplash
Para quién es esto: Fundadores solitarios e indie hackers que conocen lo básico de Python y quieren construir aplicaciones web impulsadas por datos—como herramientas SaaS, paneles internos o sitios de membresía—sin reinventar la autenticación, el enrutamiento o las migraciones de bases de datos. Incluso si eres nuevo en Django pero puedes leer Python, podrás seguir el ritmo.
Paso 1: Instalar Django y Comenzar un Nuevo Proyecto
Django requiere Python 3.8 o posterior. Crea un entorno virtual para aislar las dependencias:
python3 -m venv venv
source venv/bin/activate # En Windows: venv\Scripts\activate
pip install django
Inicia un nuevo proyecto Django:
django-admin startproject myapp
cd myapp
python manage.py runserver
Verifica http://127.0.0.1:8000/ en tu navegador. ¿Ves la página de bienvenida de Django? Eso confirma tu instalación.
Django organiza los proyectos separando la configuración (settings.py, urls.py) de la lógica de la aplicación. Un "proyecto" contiene configuraciones globales; las "aplicaciones" contienen características. Ejecutar múltiples aplicaciones dentro de un proyecto es útil si estás construyendo un SaaS con módulos distintos.
Paso 2: Crea Tu Primera Aplicación y Define Modelos
Foto: Florian Olivo en Unsplash
Las aplicaciones de Django son módulos reutilizables. Crea una:
python manage.py startapp core
Abre core/models.py y define un modelo de datos. Aquí tienes un modelo Task simple para una aplicación de tareas:
from django.db import models
class Task(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
completed = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Registra la aplicación en myapp/settings.py:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'core', # Agrega esta línea
]
Ejecuta las migraciones para crear la tabla de la base de datos:
python manage.py makemigrations
python manage.py migrate
Django utiliza un ORM (Mapeo Objeto-Relacional) que traduce clases de Python en SQL. No escribes declaraciones CREATE TABLE. Las migraciones están versionadas, por lo que puedes revertir cambios en el esquema—crítico cuando estás iterando rápidamente y rompiendo cosas.
Paso 3: Configura el Admin de Django y Prueba Operaciones CRUD
La interfaz de administración de Django está lista para producción. Crea un superusuario:
python manage.py createsuperuser
Sigue las instrucciones. Luego registra tu modelo en core/admin.py:
from django.contrib import admin
from .models import Task
@admin.register(Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ('title', 'completed', 'created_at')
list_filter = ('completed',)
search_fields = ('title',)
Ejecuta el servidor y visita http://127.0.0.1:8000/admin/. Inicia sesión con tus credenciales de superusuario. Ahora puedes crear, editar y eliminar tareas sin escribir una sola línea de código frontend.
Honestamente, el admin de Django puede ser suficiente para herramientas internas que no requieren una interfaz de usuario personalizada. Si estás construyendo un SaaS B2B con usuarios avanzados, el panel de administración puede validar tu idea antes de invertir en React o Vue. Para más información sobre herramientas para indie hackers, consulta nuestro artículo sobre las Mejores Herramientas de Despliegue de Código para Indie Hackers en 2026.
Paso 4: Construye Vistas y Enrutamiento de URL
Las vistas manejan solicitudes HTTP y devuelven respuestas. Django soporta vistas basadas en funciones (FBVs) y vistas basadas en clases (CBVs). Las CBVs reducen la repetición para patrones comunes como páginas de lista/detalle.
Crea una vista de lista en core/views.py:
from django.views.generic import ListView
from .models import Task
class TaskListView(ListView):
model = Task
template_name = 'core/task_list.html'
context_object_name = 'tasks'
ordering = ['-created_at']
Conéctalo en myapp/urls.py:
from django.contrib import admin
from django.urls import path
from core.views import TaskListView
urlpatterns = [
path('admin/', admin.site.urls),
path('', TaskListView.as_view(), name='task-list'),
]
Crea un directorio de plantillas: core/templates/core/task_list.html:
<!DOCTYPE html>
<html>
<head>
<title>Tareas</title>
</head>
<body>
<h1>Mis Tareas</h1>
<ul>
{% for task in tasks %}
<li>
{{ task.title }}
{% if task.completed %}✓{% endif %}
</li>
{% empty %}
<li>Aún no hay tareas.</li>
{% endfor %}
</ul>
</body>
</html>
Visita http://127.0.0.1:8000/. Verás tu lista de tareas. Aunque el motor de plantillas de Django puede carecer del poder de Jinja2, es suficiente para HTML renderizado en el servidor. ¿Construyendo una aplicación primero API? Quizás salte las plantillas y use Django REST Framework.
Paso 5: Agrega Autenticación de Usuarios
Django incluye un sistema de autenticación completo. Habilita vistas de inicio/cierre de sesión agregando a myapp/urls.py:
from django.contrib.auth import views as auth_views
urlpatterns = [
path('admin/', admin.site.urls),
path('', TaskListView.as_view(), name='task-list'),
path('login/', auth_views.LoginView.as_view(template_name='core/login.html'), name='login'),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]
Crea core/templates/core/login.html:
<!DOCTYPE html>
<html>
<head>
<title>Iniciar Sesión</title>
</head>
<body>
<h1>Iniciar Sesión</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Iniciar Sesión</button>
</form>
</body>
</html>
Actualiza myapp/settings.py para establecer la redirección después del inicio de sesión:
LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'
Protege las vistas con @login_required:
from django.contrib.auth.mixins import LoginRequiredMixin
class TaskListView(LoginRequiredMixin, ListView):
model = Task
template_name = 'core/task_list.html'
context_object_name = 'tasks'
ordering = ['-created_at']
login_url = '/login/'
Ahora los usuarios no autenticados son redirigidos a iniciar sesión. El sistema de autenticación de Django maneja el hash de contraseñas, la gestión de sesiones y los permisos. No necesitas Auth0 o Firebase Auth para la mayoría de los proyectos individuales.
Según la documentación de Django, el modelo de usuario incorporado admite campos personalizados a través de AbstractUser o AbstractBaseUser si necesitas inicio de sesión solo con correo electrónico o multi-tenencia.
Paso 6: Conectar una Base de Datos de Producción y Configurar Ajustes
Django utiliza SQLite por defecto, lo cual está bien para prototipos, pero es arriesgado en producción. PostgreSQL es la opción estándar para aplicaciones Django.
Instala el adaptador de PostgreSQL:
pip install psycopg2-binary
Actualiza myapp/settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'myapp_db',
'USER': 'myapp_user',
'PASSWORD': 'secure_password',
'HOST': 'localhost',
'PORT': '5432',
}
}
Para producción, usa variables de entorno. Instala python-decouple:
pip install python-decouple
Actualiza la configuración:
from decouple import config
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST', default='localhost'),
'PORT': config('DB_PORT', default='5432'),
}
}
SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
Crea un archivo .env:
SECRET_KEY=your-secret-key-here
DEBUG=True
DB_NAME=myapp_db
DB_USER=myapp_user
DB_PASSWORD=secure_password
DB_HOST=localhost
DB_PORT=5432
Nunca cometas .env en el control de versiones. Agrégalo a .gitignore.
El módulo de configuración de Django es código Python, por lo que puedes importar bibliotecas, establecer condicionales y organizar la configuración como desees. Algunos desarrolladores dividen la configuración en base.py, dev.py y prod.py. Vale la pena mencionar: mantener un solo archivo con variables de entorno puede reducir la confusión.
Paso 7: Desplegar a Producción
Las aplicaciones Django se ejecutan en cualquier servidor WSGI. Opciones populares para fundadores solitarios:
- Render: Nivel gratuito, despliega desde GitHub, PostgreSQL gestionado.
- Railway: Precios simples, bases de datos integradas, despliegues con un comando.
- DigitalOcean App Platform: Nivel inicial de $5/mes, escala con el uso.
Te mostraré Render porque es el camino más rápido hacia una URL en vivo.
Crea un requirements.txt:
pip freeze > requirements.txt
Agrega gunicorn (servidor WSGI):
pip install gunicorn
pip freeze > requirements.txt
Crea un render.yaml en la raíz de tu proyecto:
services:
- type: web
name: myapp
env: python
buildCommand: pip install -r requirements.txt && python manage.py migrate
startCommand: gunicorn myapp.wsgi:application
envVars:
- key: SECRET_KEY
generateValue: true
- key: DEBUG
value: False
- key: DATABASE_URL
fromDatabase:
name: myapp-db
property: connectionString
databases:
- name: myapp-db
databaseName: myapp_db
user: myapp_user
Envía tu código a GitHub. Conecta tu repositorio a Render. Detecta automáticamente Django, provisiona una instancia de PostgreSQL y despliega.
Actualiza myapp/settings.py para analizar DATABASE_URL:
pip install dj-database-url
import dj_database_url
DATABASES = {
'default': dj_database_url.config(
default=config('DATABASE_URL')
)
}
Establece ALLOWED_HOSTS:
ALLOWED_HOSTS = [config('ALLOWED_HOSTS', default='localhost')]
En el panel de Render, agrega ALLOWED_HOSTS=your-app.onrender.com. Vuelve a desplegar. Tu aplicación está en vivo.
Según la documentación de Render, su plataforma maneja certificados SSL, escalado automático y despliegues sin tiempo de inactividad. No necesitas lidiar con configuraciones de Nginx o servicios systemd.
Lo Que Nadie Te Dice Sobre Django
El ORM no es magia. Django genera SQL por ti, pero las consultas ineficientes aún pueden ocurrir. Usa select_related() y prefetch_related() para evitar problemas de N+1. ¿Aplicaciones de producción que hacen más de 300 consultas a la base de datos por vista de página? Sí, eso sucede cuando los desarrolladores asumen que el ORM optimiza todo.
Las migraciones se rompen de maneras que la documentación no advierte. Modificar un modelo, ejecutar makemigrations, luego cambiar de opinión y editar el archivo de migración manualmente? Eso puede desordenar el gráfico de migración de Django. Siempre ejecuta migrate inmediatamente después de makemigrations en desarrollo. Prueba las migraciones en una base de datos de staging primero en producción.
El soporte asíncrono de Django es incompleto. Django 3.1 agregó soporte ASGI, pero la mayoría de los paquetes de terceros asumen WSGI. ¿Necesitas WebSockets o tareas de larga duración? Usa Celery con Redis o RabbitMQ. ¿Ejecutando vistas asíncronas en producción sin pruebas de carga? Prepárate: las aplicaciones pueden fallar debido a middleware que no es seguro para asíncrono.
El panel de administración tiene límites. Personalizar flujos de trabajo complejos en el panel de administración requiere sobrescribir plantillas y escribir acciones de administración. ¿Necesitas una interfaz de usuario pulida para usuarios no técnicos? Construye un frontend real. El panel de administración es más adecuado para herramientas internas y usuarios avanzados que pueden tolerar interfaces menos pulidas.
Django REST Framework es una curva de aprendizaje separada. DRF es el estándar para construir APIs, pero introduce conceptos de serializadores, viewsets y routers. ¿Nuevo en Django? Primero, construye una aplicación CRUD simple con plantillas. Agregar DRF sin entender el ORM de Django o el ciclo de solicitud/respuesta podría confundirte.
Errores Comunes
Omitir variables de entorno en desarrollo. Los desarrolladores codifican DEBUG=True y SECRET_KEY en settings.py, y luego se olvidan de cambiarlos antes de desplegar. Usa archivos .env desde el primer día. Cinco minutos de configuración previenen desastres en producción.
Ignorar índices de base de datos. Django no indexa automáticamente las claves foráneas en todas las bases de datos. Si filtras por un campo con frecuencia—como Task.objects.filter(user=request.user)—agrega db_index=True:
user = models.ForeignKey(User, on_delete=models.CASCADE, db_index=True)
No usar get_object_or_404. Los principiantes escriben:
task = Task.objects.get(pk=task_id)
Esto genera DoesNotExist si el objeto falta, lo que hace que la aplicación se bloquee. En su lugar, usa:
from django.shortcuts import get_object_or_404
task = get_object_or_404(Task, pk=task_id)
Esto devuelve automáticamente una respuesta 404.
Mezclar lógica de negocio en las vistas. Las vistas solo deben manejar la lógica HTTP—validación, redirecciones, contexto. Mueve cálculos, llamadas a APIs externas y procesamiento de datos a métodos de modelo o módulos de servicio. Modelos gruesos, vistas delgadas.
Preguntas Frecuentes
¿Puedo usar Django para una aplicación de una sola página con React o Vue?
Sí. Django se convierte en tu backend API. Instala Django REST Framework, construye serializadores para tus modelos y expón endpoints. Tu frontend consume JSON. Honestamente, así es como la mayoría de los proyectos se envían—Django para autenticación y lógica de base de datos, React para la interfaz de usuario.
¿Cómo manejo las cargas de archivos en Django?
Usa FileField o ImageField en tu modelo:
avatar = models.ImageField(upload_to='avatars/')
Django guarda archivos en MEDIA_ROOT por defecto. En producción, usa S3 o Cloudflare R2 con django-storages. Servir archivos desde tu servidor de aplicaciones es lento y desperdicia memoria.
¿Es Django más lento que Flask o FastAPI?
Para la mayoría de los proyectos individuales, la diferencia no importa. Django incluye más funcionalidades—ORM, administración, autenticación—por lo que hay algo de sobrecarga. ¿Construyendo una API de alto tráfico con tiempos de respuesta inferiores a 10 ms? FastAPI es más rápido. ¿Construyendo un SaaS con formularios, cuentas de usuario y una base de datos? Django se envía más rápido porque escribes menos código.
¿Cómo programo tareas en segundo plano en Django?
Usa Celery con Redis. Instala Celery:
pip install celery redis
Configúralo en myapp/celery.py, luego define tareas:
from celery import shared_task
@shared_task
def send_email(user_id):
# Lógica del correo aquí
pass
Llama a la tarea con .delay():
send_email.delay(user.id)
Esto ejecuta la tarea de forma asíncrona. No ejecutes tareas largas en las vistas de Django—los usuarios esperan la respuesta y tu aplicación se cuelga.
Conclusión
Django intercambia flexibilidad por velocidad. Obtienes autenticación, migraciones y un panel de administración sin configuración. ¿Validando una idea de SaaS y necesitas enviar en días? Django es la herramienta adecuada.
Tu próximo paso: clona el repositorio inicial o crea un nuevo proyecto, define un modelo y despliega esta noche en Render o Railway. Deja de leer tutoriales y envía algo en vivo. Aprenderás más en producción que en 50 artículos. Para recursos adicionales, considera explorar las Mejores Soluciones de Pago en Línea para Indie Hackers en 2026.
Nota editorial: Este artículo fue elaborado con asistencia de IA y revisado por Javier Valencia. A lo largo del texto se distinguen los hechos verificados de la opinión editorial. Las fuentes externas enlazadas son independientes de NewsTide.