Módulo 4 · Lección 7 de 45
Las aplicaciones dentro del proyecto
Por qué un proyecto de Django se parte en trozos, dónde va por fin tu código, y el olvido que no da ningún error.
En la lección 6 escribiste una vista en el paquete de configuración, y quedó dicho que ese no era su sitio. Ahora se muda.
Las aplicaciones son la unidad en la que Django parte un proyecto, y el nombre confunde: no son programas, son carpetas con una estructura pactada. Un proyecto es un conjunto de aplicaciones, y las cuatro que vienen puestas de fábrica —la autenticación, el panel de administración, las sesiones— son aplicaciones exactamente iguales que las que vas a escribir tú.
Por qué partir el proyecto#
La razón de fondo es que Django se diseñó en un periódico, para una redacción que tenía una web de noticias, otra de clasificados y otra de eventos, y todas necesitaban lo mismo: usuarios, comentarios, etiquetas, un buscador. La idea fue que esas piezas comunes se pudieran escribir una vez y enchufar en los tres sitios.
De ahí sale la definición práctica: una aplicación es un trozo del proyecto que hace una cosa y que podrías llevarte a otro proyecto. La agenda de contactos es una. El blog de la empresa sería otra. El sistema de usuarios es otra, y esa ni la escribes tú porque viene con Django.
En un proyecto pequeño, esa capacidad de llevártela no la vas a usar nunca, y sin embargo la división sigue mereciendo la pena por lo que impone: cada aplicación tiene sus modelos, sus vistas, sus plantillas y sus pruebas en su carpeta, y cuando abras el proyecto dentro de seis meses sabrás dónde mirar.
Crearla#
python manage.py startapp contactosNo imprime nada. Ha creado esto:
contactos/
__init__.py Vacío: declara que es un paquete
apps.py La configuración de la aplicación
models.py Los modelos. Bloque B
views.py Las vistas. Bloque C
admin.py Qué se registra en el panel de administración. Bloque E
tests.py Las pruebas. Lección 39
migrations/ Las migraciones, de momento vacíaCasi todos nacen con un comentario dentro y nada más:
from django.shortcuts import render
# Create your views here.La carpeta está al lado de manage.py, no dentro del paquete de configuración. Y faltan dos cosas que vas a crear a mano en cuanto hagan falta, porque startapp no las pone: urls.py, que se hace en esta misma lección, y la carpeta templates/, que llega en el bloque C.
Registrarla#
Una aplicación creada no está puesta. Hay que añadirla a INSTALLED_APPS, al final de la lista:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'contactos',
]Con esa línea, Django ya sabe que la aplicación existe y empieza a mirar dentro: busca sus modelos para crear las tablas, sus plantillas al renderizar, sus pruebas al ejecutar test y su admin.py al montar el panel.
Mudar la vista#
Ahora se mueve lo de la lección 6. La vista pasa a contactos/views.py, con el nombre de fichero que usa Django:
from django.http import HttpResponse
def lista(peticion):
nombres = ["Ana Ruiz", "Luis Pardo"]
filas = "".join(f"<li>{n}</li>" for n in nombres)
return HttpResponse(f"<h1>Contactos</h1><ul>{filas}</ul>")Dos cambios respecto a como estaba. El fichero se llama views.py en inglés, porque ese nombre lo impone Django en unos cuantos sitios y no es negociable como sí lo era el de vistas.py. Y la función se llama lista y no contactos, porque ya está dentro de la aplicación de contactos y repetir la palabra sobra: la dirección acabará siendo contactos.lista.
Su propio fichero de rutas#
Aquí está el reparto que hace escalable un proyecto. En vez de que el urls.py del proyecto conozca todas las direcciones, cada aplicación declara las suyas y el proyecto solo dice por dónde cuelgan.
Crea contactos/urls.py:
from django.urls import path
from . import views
app_name = 'contactos'
urlpatterns = [
path('', views.lista, name='lista'),
]Y en el del proyecto, include:
from django.contrib import admin
from django.urls import include, path
from . import vistas
urlpatterns = [
path('', vistas.portada),
path('contactos/', include('contactos.urls')),
path('admin/', admin.site.urls),
]include hace algo muy concreto: le corta a la ruta el trozo que ya ha encajado y le pasa el resto al otro fichero. Una petición a /contactos/ encaja con 'contactos/', y lo que queda es la cadena vacía, que es lo que contactos/urls.py compara con sus patrones. Por eso el patrón de dentro es '' y no 'contactos/': la aplicación no sabe ni tiene que saber bajo qué dirección la han colgado.
Esa ignorancia es justo lo que la hace reutilizable. Si mañana la agenda tiene que vivir en /agenda/personas/, se cambia una línea del proyecto y dentro de la aplicación no se toca nada.
Comprueba que sigue funcionando:
curl -s http://127.0.0.1:8000/contactos/<h1>Contactos</h1><ul><li>Ana Ruiz</li><li>Luis Pardo</li></ul>Lo mismo que antes, y ahora el código está donde tiene que estar. Ya puedes borrar agenda/vistas.py, dejando en el paquete de configuración solo la vista de la portada o moviéndola también a una aplicación propia.
apps.py y una sorpresa de la versión#
El fichero que menos se toca:
from django.apps import AppConfig
class ContactosConfig(AppConfig):
name = 'contactos'Sirve para dos cosas. Una es ponerle un nombre legible a la aplicación, que es el que sale en el panel de administración:
class ContactosConfig(AppConfig):
name = 'contactos'
verbose_name = 'Agenda de contactos'La otra es el método ready(), que Django llama cuando la aplicación está cargada del todo. Es el sitio correcto para las señales, y aparece en el bloque E.
Con qué criterio se parte#
La pregunta que sigue es cuántas aplicaciones hacen falta. No hay una respuesta buena, pero sí dos malas muy frecuentes.
Una es una sola aplicación para todo, normalmente llamada core o principal, con cuarenta modelos dentro. Funciona y renuncia a lo único que aportaba la división, que es saber dónde está cada cosa.
La otra es una aplicación por modelo. Se acaba con quince carpetas de tres líneas cada una, importándose entre ellas en todas las direcciones, que es peor que no haber partido nada.
El criterio que funciona es preguntarse si el trozo tiene sentido por sí solo. La agenda de contactos lo tiene: se entiende sin saber nada del resto del proyecto. Un modelo de "grupo de contacto" no lo tiene, porque solo existe para los contactos; va dentro de la misma aplicación.
Para este módulo, la agenda es una aplicación y punto. Los dos proyectos del final tendrán dos o tres, y ahí se verá el reparto con más de una pieza sobre la mesa.