Sobre mí

José Miguel Amaya Camacho

Perfil

Desarrollador Python/Django. Full Stack en Xprende Tech (Ecuador) e Infobibliotecas (España). Fundador de Python Piura.

Hoy

Un vistazo rápido pero completo a Django: qué trae, cómo se organiza y cómo se construye un blog mínimo.

GitHub github.com/joseamaya
Twitter @jamayac99
La comunidad

Python Piura

Qué hacemos

Eventos, charlas y talleres para difundir Python en Piura y la región.

Dónde escribimos

Un blog con experiencias en Python, Django, Odoo y más.

Súmate

Comunidad abierta a todos los niveles: estudiantes, profesionales y curiosos.

Web pythonpiura.org
Hoy Python Piura · Piura AI
Agenda

Qué vamos a ver

  • 01 Qué es Django, filosofía y MTV 10 min
  • 02 Preparar el entorno y el proyecto 10 min
  • 03 Las piezas: modelos, ORM, admin, vistas y plantillas 25 min
  • 04 El ciclo completo y siguientes pasos 5 min
01

Django

Qué es, en qué cree y cómo piensa.

Punto de partida

¿Qué es Django?

Framework web completo

Gratuito y open source, escrito en Python. Nació en 2005 en el Lawrence Journal-World.

Lado del servidor

Trabaja el backend: enrutado, base de datos, autenticación, formularios, plantillas.

Sin ataduras

Soporta múltiples bases de datos y se despliega en varios servidores web.

✓
Detrás de sitios como Instagram, Mozilla, Pinterest o Eventbrite: Django escala.
Cómo piensa

Filosofía de Django

Agilidad

Del concepto al producto sin montar media infraestructura.

Bajo acoplamiento

Componentes independientes que puedes cambiar por separado.

DRY

Don't Repeat Yourself: la lógica vive en un solo lugar.

URLs limpias

Direcciones legibles y mapeadas explícitamente.

Versatilidad

De un blog a una plataforma enorme con la misma base.

MTV

Model Template View: una variación del clásico MVC.

El patrón

MTV: tres preguntas, tres piezas

¿Cómo se almacena el dato?
Modelo

La clase Python que describe la tabla en la base de datos.

¿Qué dato se muestra?
Vista

La función o clase que decide qué consultar y qué responder.

¿Cómo se muestra el dato?
Template

El HTML con marcadores que da forma a la respuesta.

La idea en una imagen

El flujo de Django

Usuario · persona con navegador Navegador URLs Vistas Modelos (ORM) Base de datos Templates petición resuelve datos SQL render HTML El navegador recibe HTML; el ciclo se repite en cada petición
Baterías incluidas

Qué trae Django de fábrica

ORM

Base de datos con objetos Python.

Admin

Panel de gestión listo.

Auth

Usuarios, grupos y permisos.

Migraciones

Cambios de esquema versionados.

Plantillas

HTML reutilizable y heredable.

Forms

Validación de datos de entrada.

i18n

Traducciones y zonas horarias.

Seguridad

CSRF, XSS, SQLi y sesiones.

Contexto

Django, Flask y FastAPI

DjangoFlaskFastAPI
EnfoqueFull-stackMicro, flexibleMicro, async
ORMIncluidoExtensionesSQLAlchemy/SQLModel
AdminIncluido——
ValidaciónFormsExtensionesPydantic
Ideal paraPortales y sistemas completosApps pequeñasAPIs y servicios
i
No hay framework "mejor": hay herramientas para cada problema. Django brilla cuando necesitas el paquete completo.
Contexto

Piezas incluidas de fábrica

Comparación ilustrativa de áreas cubiertas sin plugins; no es un benchmark.

02

Preparación

Del entorno virtual al primer servidor corriendo.

Paso 1

El entorno virtual

Un entorno aislado con su propia copia de Python y sus dependencias.

zsh — terminal
$ mkdir taller && cd taller $ python3 -m venv .venv $ source .venv/bin/activate # Windows: .venv\Scripts\activate (.venv) $
i
Antes se usaba virtualenv; hoy venv viene incluido en Python. El prompt (.venv) confirma que está activo.
Paso 2

Instalar Django

zsh — terminal
(.venv) $ pip install "Django>=5.2,<6" Collecting Django>=5.2,<6 Successfully installed django-5.2.7 ... (.venv) $ pip freeze > requirements.txt
✓
pip freeze deja las versiones exactas en requirements.txt: tu proyecto es reproducible en otra máquina.
Paso 3

Crear el proyecto

zsh — terminal
(.venv) $ django-admin startproject taller . (.venv) $ ls manage.py taller/
✓
El punto al final evita la carpeta taller/taller/ duplicada: manage.py queda en la raíz del proyecto.
Paso 4

Estructura del proyecto

taller/ — árbol
taller/
├── manage.py
├── requirements.txt
└── taller/
    ├── __init__.py
    ├── settings.py
    ├── urls.py
    ├── asgi.py
    └── wsgi.py
  • settings.pyapps, base de datos, idioma, zona horaria…
  • urls.pyenruta cada URL a una vista
  • asgi.pyentrada ASGI (async) para producción
  • wsgi.pyentrada WSGI clásica para producción
  • manage.pycomandos de administración del proyecto
Paso 5

La aplicación blog

zsh — terminal
(.venv) $ python manage.py startapp blog (.venv) $ ls blog admin.py apps.py models.py tests.py views.py migrations/
blog/ — árbol
blog/
├── migrations/
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
i
No olvides agregar "blog" a INSTALLED_APPS: es el error número uno de todo principiante.
Paso 6

Arrancar el proyecto

zsh — terminal
(.venv) $ python manage.py migrate Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: Applying contenttypes.0001_initial... OK ... (16 migraciones más) (.venv) $ python manage.py runserver Watching for file changes with StatReloader Starting development server at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
!
El servidor de desarrollo es solo para local: en producción se usa gunicorn/uvicorn detrás de nginx.
Paso 7

El admin y el superusuario

  • /admin/panel ya construido para gestionar usuarios y datos
  • createsuperuseracceso total al admin y a las apps registradas
zsh — terminal
(.venv) $ python manage.py createsuperuser Nombre de usuario: miguel Correo electrónico: miguel@example.com Password: ******** Superuser created successfully.
03

Las piezas

Modelos, ORM, admin, vistas y plantillas con un blog mínimo.

Organización

Proyecto y aplicación

Proyecto

Contiene la configuración y los componentes del sitio: settings, urls, wsgi/asgi. Nuestro taller.

Aplicación

Un componente con una funcionalidad concreta: blog, usuarios, foros, galería… Cada una con sus modelos y vistas.

i
Un proyecto puede contener muchas apps; una app puede reutilizarse en varios proyectos (Django trae varias de serie: admin, auth…).
Configuración

settings.py

taller/settings.py
INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "blog",
]

LANGUAGE_CODE = "es-pe"
TIME_ZONE = "America/Lima"
i
Aquí viven la base de datos, los idiomas, la zona horaria y las apps activas. En producción suele haber uno por entorno (local, testing, prod).
Enrutado

urls.py

taller/urls.py
from django.contrib import admin
from django.urls import path

from blog import views

urlpatterns = [
    path("admin/", admin.site.urls),
    path("articulos/", views.lista_articulos, name="lista_articulos"),
]
i
Django 2+ usa path() con convertidores (<int:pk>); en 2017 esto se escribía con url() y expresiones regulares. Un urls.py por app mantiene todo ordenado.
Pieza 1

Los modelos

  • Descripciónlos datos en código Python que se reflejan en tablas de la base de datos.
  • SQL por detráscada consulta ejecuta SQL y devuelve objetos Python cómodos.
  • models.pycada aplicación declara ahí sus modelos.
✓
Nuestro blog: un modelo Articulo con título, cuerpo, estado de publicación y fecha de creación.
Pieza 1

models.py

blog/models.py
from django.db import models


class Articulo(models.Model):
    titulo = models.CharField(max_length=120)
    cuerpo = models.TextField()
    publicado = models.BooleanField(default=True)
    creado = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.titulo

    class Meta:
        ordering = ("-creado",)
i
CharField y TextField son los campos de texto; auto_now_add pone la fecha al crear. __str__ hace legible el objeto en el admin.
Pieza 1

Las migraciones

El historial versionado de los cambios de tus modelos, en archivos Python.

1

Cambias models.py

añades o modificas un campo
→
2

makemigrations

genera el archivo de migración en migrations/
→
3

migrate

aplica los cambios a la base de datos
!
Cambiaste un modelo y no migraste: la tabla no existe. Es el error más frecuente al empezar.
Pieza 2

El ORM de Django

Object Relational Mapping: mapeo objeto-relacional.

  • Sin SQLconsultas y escrituras con métodos Python; el ORM genera el SQL.
  • Objetoscrear, modificar, eliminar y consultar de forma individual o en conjunto.
  • Portableel mismo código funciona en PostgreSQL, MariaDB, SQLite…
✓
La puerta de entrada es python manage.py shell: un intérprete con Django cargado.
Pieza 2

ORM en acción

python manage.py shell
>>> from blog.models import Articulo >>> Articulo.objects.create(titulo="Hola Django", cuerpo="Mi primer post") <Articulo: Hola Django> >>> Articulo.objects.all() <QuerySet [<Articulo: Hola Django>]> >>> Articulo.objects.filter(publicado=True).order_by("-creado") <QuerySet [<Articulo: Hola Django>]>
i
create() inserta, all() trae todo, filter() filtra y order_by() ordena. Detrás de cada línea hay SQL generado por Django.
Pieza 3

El admin en la práctica

blog/admin.py
from django.contrib import admin

from blog.models import Articulo


admin.site.register(Articulo)
127.0.0.1:8000/admin/blog/articulo/admin
Selecciona artículo para cambiarAÑADIR ARTÍCULO
Hola DjangoPublicado
Plantillas y herenciaPublicado
Django 5.2 LTSBorrador
Pieza 4

Las vistas

  • Entradareciben un objeto con la petición: método (GET/POST), ruta, datos…
  • Salidadevuelven una respuesta: HTML renderizado, una redirección o un error.
  • views.pycada aplicación declara ahí sus vistas; pueden ser funciones o clases.
✓
Nuestra primera vista: consultar los artículos publicados y pasarlos a una plantilla.
Pieza 4

views.py

blog/views.py
from django.shortcuts import render

from blog.models import Articulo


def lista_articulos(request):
    articulos = Articulo.objects.filter(publicado=True)
    return render(request, "blog/lista.html", {"articulos": articulos})
i
render() une tres cosas: la petición, la plantilla y el contexto (los datos que la plantilla usará).
Pieza 5

Las plantillas

  • HTML + etiquetas{{ variable }} inserta datos; {% etiqueta %} controla la lógica.
  • ¿Dónde viven?en templates/ de cada app, o una carpeta global del proyecto.
  • Herencialas plantillas se extienden y se reutilizan: una base, muchas páginas.
✓
El HTML final se arma con datos en el servidor; el navegador solo recibe el resultado.
Pieza 5

Herencia de plantillas

blog/templates/base.html
<!doctype html>
<html lang="es">
<head>
  <title>
    {% block titulo %}Mi blog{% endblock %}
  </title>
</head>
<body>
  {% block contenido %}{% endblock %}
</body>
</html>
blog/templates/blog/lista.html
{% extends "base.html" %}

{% block titulo %}Artículos{% endblock %}

{% block contenido %}
  {% for articulo in articulos %}
    <h2>{{ articulo.titulo }}</h2>
  {% endfor %}
{% endblock %}
i
extends hereda la base; block rellena las partes; for recorre el contexto que envió la vista.
Pieza 6

Archivos estáticos

CSS, JavaScript e imágenes: lo que no cambia con cada petición.

  • static/una carpeta por app, o una global del proyecto.
  • {% static %}genera la URL correcta de cada archivo en las plantillas.
  • collectstaticreúne todo para servirlo en producción (nginx, S3…).
taller/settings.py
STATIC_URL = "static/"
STATICFILES_DIRS = [BASE_DIR / "static"]
Mapa final

El proyecto completo

taller/ — con la app blog
taller/
├── manage.py
├── requirements.txt
├── taller/
│   ├── settings.py
│   ├── urls.py
│   └── ...
└── blog/
    ├── models.py            # Articulo
    ├── views.py             # lista_articulos
    ├── admin.py             # admin.site.register
    ├── migrations/          # historial de la BD
    ├── templates/blog/      # base.html, lista.html
    └── static/blog/         # estilos.css
Todo junto

El viaje de una petición

PeticiónGET /articulos/
→
URLselige la vista
→
Vistaconsulta y arma el contexto
→
Modelos (ORM)traducen a consultas SQL
→
Base de datosdevuelve las filas
→
Templaterenderiza el HTML
✓
Y de vuelta al navegador: HTML listo para mostrar. Cada clic repite este ciclo en milisegundos.
04

Cierre

Lo que viene después y cómo evitar los tropiezos típicos.

El puente

Django REST Framework

Django pone la base

Modelos, ORM, autenticación, admin y migraciones: el motor de datos y la lógica.

DRF añade la capa API

Serializers, vistas y routers para exponer todo eso como una API REST con JSON.

i
Cuando tu web necesite una app móvil, una integración o un frontend separado, el siguiente paso natural es DRF.
Aprendiendo de los errores

Errores comunes

Olvidar la app en INSTALLED_APPS

Síntoma: no aparecen tablas, ni admin, ni plantillas. Django no sabe que tu app existe.

Cambiar el modelo sin migrar

makemigrations + migrate después de cada cambio. Sin eso, la tabla no existe.

DEBUG=True en producción

Expone información interna. Se apaga con variables de entorno, igual que SECRET_KEY.

Commitear la base de datos

db.sqlite3 y .venv/ van al .gitignore: son locales, no código.

Para seguir

Siguientes pasos

Vistas basadas en clases Formularios Tests PostgreSQL DRF Despliegue (gunicorn/uvicorn) Docker Celery Cache i18n
✓
Django es un ecosistema: no hay que aprenderlo todo de golpe. Elige el siguiente paso que tu proyecto necesite.
Para llevar

Recursos

Documentacióndocs.djangoproject.com/es/5.2/
Tutorial oficialdocs.djangoproject.com/es/5.2/intro/tutorial01/
Comunidadpythonpiura.org · Python Piura · Piura AI
Este deckjoseamaya.github.io/introduccion-a-django/
✓
El tutorial oficial de Django es de los mejores que existen: en 7 partes construyes una app completa.