Debido a que Django fue desarrollado en un ambiente ágil de redacción, se diseñó para que las tareas comunes de desarrollo web fueran rápidas y simples. Lo que sigue es un vistazo a la forma de codificar una aplicación web con base de datos (database-driven Web app) usando Django.
El objetivo de este documento es dar suficiente información técnica para entender cómo funciona Django, pero no pretende ser un tutorial o referencia - ¡aunque tenemos ambas cosas! Cuando estés listo para empezar un proyecto con Django puedes leer el tutorial o ir directamente a la documentación más detallada.
Aunque es posible usar Django sin una base de datos, Django incluye un mapeador objeto-relacional en el que es posible describir la estructura de la base de datos usando Python.
La sintaxis del modelo de datos ofrece muchas formas de representar los modelos -- hasta ahora ha estado resolviendo problemas con bases de datos por más de dos años. Aquí hay un ejemplo rápido:
class Reporter(models.Model):
full_name = models.CharField(maxlength=70)
def __unicode__(self):
return self.full_name
class Article(models.Model):
pub_date = models.DateTimeField()
headline = models.CharField(maxlength=200)
article = models.TextField()
reporter = models.ForeignKey(Reporter)
def __unicode__(self):
return self.headline
Con el modelo listo, ejecuta la utilidad de línea de comandos para crear automáticamente las tablas de la base de datos:
manage.py syncdb
El comando syncdb revisa todos los modelos disponibles y crea las tablas correspondientes en la base de datos si no existían previamente.
Con eso hemos conseguido, sin mayor esfuerzo, una expresiva API para acceder a tus datos. La API se crea al vuelo, sin necesidad de generar código:
>>> from mysite.models import Reporter, Article
# Aún no hay reporteros en el sistema
>>> Reporter.objects.all()
[]
# Creamos un nuevo reportero.
>>> r = Reporter(full_name='John Smith')
# Grabamos el objeto en la base de datos. Debes llamar a save() explícitamente.
>>> r.save()
# Ahora tiene un ID
>>> r.id
1
# Ahora hay un nuevo reportero en la base de datos.
>>> Reporter.objects.all()
[John Smith]
# Los campos son representados como atributos en un objeto Python.
>>> r.full_name
'John Smith'
# Django provee una rica API para búsqueda de datos.
>>> Reporter.objects.get(id=1)
John Smith
>>> Reporter.objects.get(full_name__startswith='John')
John Smith
>>> Reporter.objects.get(full_name__contains='mith')
John Smith
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Reporter does not exist for {'id__exact': 2}
# Creamos un artículo.
>>> from datetime import datetime
>>> a = Article(pub_date=datetime.now(), headline='Django is cool',
... article='Yeah.', reporter=r)
>>> a.save()
# Ahora el artículo está en la base de datos.
>>> Article.objects.all()
[Django is cool]
# Los objetos Article tienen una API para acceder a los objetos Reporter
# relacionados.
>>> r = a.reporter
>>> r.full_name
'John Smith'
# Y viceversa: Los objetos Reporter tienen una API para acceder a los
# objetos Article.
>>> r.article_set.all()
[Django is cool]
# La API sigue las relaciones hasta donde se requiere, ejecutando JOINs
# eficientes tras bambalinas.
# La instrucción que sigue encuentra todos los artículos de un reportero
# cuyo nombre comience con "John".
>>> Article.objects.filter(reporter__full_name__startswith="John")
[Django is cool]
# Un objeto se modifica alterando sus atributos y llamando a save().
>>> r.full_name = 'Billy Goat'
>>> r.save()
# Un objeto se elimina con delete().
>>> r.delete()
Una vez que los modelos están definidos, Django puede crear automáticamente una interfaz de administración profesional y lista para producción -- un sitio web que permite a los usuarios autenticados agregar, cambiar y eliminar objetos. Es tan fácil como registrar tu modelo en el sitio de administración:
# En models.py...
from django.db import models
class Article(models.Model):
pub_date = models.DateTimeField()
headline = models.CharField(maxlength=200)
article = models.TextField()
reporter = models.ForeignKey(Reporter)
class Admin: pass
# En admin.py en el mismo directorio...
import models
from django.contrib import admin
admin.site.register(models.Article)
La filosofía aquí es que el sitio puede ser modificado por personal administrativo, o por un cliente, o tal vez por el mismo desarrollador -- y no hay que preocuparse de crear interfaces de administración sólo para gestionar contenido.
Un flujo de trabajo típico en la creación de aplicaciones Django es crear modelos y habilitar el sitio de administración tan rápido como sea posible, de forma que el personal (o los clientes) puedan comenzar a introducir datos. Luego, desarrollar la forma en que los datos son presentados al público.
Un esquema de URLs limpio y elegante es un detalle importante en una aplicación web de alta calidad. Django incentiva el diseño de URLs elegante y no agrega ningún lastre a las URLs, como .php o .asp.
Para diseñar las URLs de la aplicación, se crea un módulo Python llamado URLconf: es como una tabla de contenidos para la aplicación que contiene un mapeo simple entre patrones de URLs y funciones Python. Las URLconfs también sirven para desacoplar las URLs del código Python.
Así es como una URLconf luce para el ejemplo de más arriba:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^/articles/(\d{4})/$', 'mysite.views.year_archive'),
(r'^/articles/(\d{4})/(\d{2})/$', 'mysite.views.month_archive'),
(r'^/articles/(\d{4})/(\d{2})/(\d+)/$', 'mysite.views.article_detail'),
)
Este código asocia URLs, como simples expresiones regulares, a la ubicación de funciones Python ("vistas"). Las expresiones regulares usan paréntesis para "capturar" valores de las URLs. Cuando un usuario solicita una página, Django pasa por cada patrón, en orden, y se detiene en el primero que coincida con la URL solicitada. (Si ninguno coincide, Django llama una vista especial 404). Esto es increíblemente rápido, porque las expresiones regulares son compiladas cuando se carga el código.
Una vez que una de las expresiones coincide, Django importa y llama la vista correspondiente, la cual es una simple función Python. Cada vista recibe un objeto request -- que contiene la metadata de la petición -- y los valores capturados en la expresión regular.
Por ejemplo, si un usuario solicita la URL "/articles/2007/05/39323/", Django llamaría a la función mysite.views.article_detail(request, '2007', '05', '39323').
Cada vista (view) es responsable de hacer una de dos cosas: Devolver un objeto HttpResponse con el contenido de la página solicitada, o lanzar una excepción como Http404. Lo demás es responsabilidad del
desarrollador.
Generalmente, una vista recupera datos de acuerdo a los parámetros, carga una plantilla y la rellena con los datos recuperados. Aquí hay un vista de ejemplo para el year_archive visto anteriormente:
def year_archive(request, year):
a_list = Article.objects.filter(pub_date__year=year)
return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
Este ejemplo usa el sistema de plantillas de Django, el que posee varias características poderosas pero es lo suficientemente simple para poder ser usado por no programadores.
El código anterior carga la plantilla news/year_archive.html.
Diango tiene una ruta de búsqueda de plantillas, lo que permite minimizar la redundancia entre ellas. En la configuración de Django, es posible especificar una lista de directorios donde se buscarán las plantillas. Si una plantilla no existe en el primer directorio, se busca en el siguiente, y así sucesivamente.
Supongamos que se encontró la plantilla news/article_detail.html. Aquí hay un ejemplo de cómo podría lucir esa plantilla:
{% extends "base.html" %}
{% block title %}Articulos de {{ year }}{% endblock %}
{% block content %}
<h1>Articulos de {{ year }}</h1>
{% for article in article_list %}
<p>{{ article.headline }}</p>
<p>Por {{ article.reporter.full_name }}</p>
<p>Publicado {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}
Las variables están encerradas por llaves dobles. {{ article.headline }} significa "Desplegar el valor del atributo headline de article". Pero los puntos no sólo son usados para búsqueda de atributos: También pueden servir para búsquedas de claves en diccionarios, búsqueda de índices y llamadas a funciones.
Notemos que {{ article.pub_date|date:"F j, Y" }} usa un "pipe" Unix (el caracter "|"). Esto se llama un filtro de plantilla, y es una forma de filtrar el valor de una variable. En este caso, el filtro date da formato a un objeto datetime de Python (tal como ocurre en la función date de PHP; sí, existe una idea buena en PHP).
Es posible encadenar tantos filtros como se desee. Además se pueden codificar filtros a la medida. De la misma forma, es posible codificar etiquetas (tags) de plantillas a la medida, los cuales pueden ejecutar código Python tras bambalinas.
Finalmente, Django usa el concepto de "herencia de plantillas": Eso es lo que hace {% extends "base.html" %}. Significa "Primero carga la plantilla lamada 'base', la cual tiene algunos bloques definidos, y rellénalos con los siguientes bloques". En otras palabras, permite disminuir dramáticamente la redundancia en las plantillas: Cada plantilla tiene que definir sólo lo que le es propio.
Así es como podría lucir "base.html":
<html>
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<img src="sitelogo.gif" alt="Logo" />
{% block content %}{% endblock %}
</body>
</html>
En pocas palabras, define el look-and-feel del sitio (con el logo del sitio), y provee espacios para ser rellenados por las plantillas hijas. Esto permite que el rediseño de un sitio tan fácil como cambiar un único archivo -- la plantilla base.
Además permite crear múltiples versiones de un sitio, con diferentes plantillas base, reusando las plantillas hijas. Los creadores de Django han usado esta técnica para crear ediciones para dispositivos móviles notablemente distintas de algunos sitios -- simplemente creando una nueva plantilla base.
Recuerda que no es necesario usar el sistema de plantillas de Django si es que prefieres otro sistema. Aunque el sistema de plantillas de Django está particularmente bien integrado con la capa de modelo de Django, no es obligatorio usarlo. Por la misma razón, tampoco es necesario usar la API de base de datos de Django. Es posible utilizar otra capa de abstracción de datos, es posible leer archivos XML, leer archivos desde el disco, o lo que se quiera. Cada pieza de Django -- modelos, vistas, plantillas -- está desacoplada del resto.
Esta ha sido sólo una vista rápida a la funcionalidad de Django. Otras características útiles son:
Los siguientes pasos obvios son descargar Django, leer el tutorial y unirte a la comunidad. ¡Gracias por tu interés!