Sei sulla pagina 1di 17

T utorial de Django http://davidasorey.

net/static/django-tutorial/

Tutorial de Django
Introducción
Requisitos
El ecosistema de Django
Estructura de (una aplicación) Django
Nuestra aplicación web: Trivial trivial
Creación del proyecto y la aplicación
Definiendo los modelos
Siguente: implementando la autentificación
Formulario de preguntas
Respondiendo a la pregunta
Conclusiones
Notas

Introducción
Django es un "framework" para el desarrollo de aplicaciones Web basado en el
lenguaje de programación Python y que sigue el patrón de diseño MVC. En los
últimos tiempos la palabra "framework" parece que se ha convertido en el "Santo
Grial" del desarrollo de aplicaciones Web.

Uno de los "framework" (1) más famosos o populares que se ha dado a conocer
ha sido Ruby On Rails. ¿Qué aporta esta herramienta frente a otras alternativas
más conocidas y establecidas?.

Lo más novedoso era la prevalencia de la convención frente a la configuración.


En vez de andar editando ficheros .xml (como en las herramientas J2EE) se
establecía una estructura de directorios estándar para la aplicación, no era
necesario configurar mapeos, plantillas, etc.

Rails también abstrae completamente la interacción con bases de datos


relacionales: el sistema es capaz de "adivinar" los modelos e inferir los objetos que
intervienen en la aplicación con sólo examinar la definición de tablas en el sistema
relacional. Hay un objeto, "ActiveRecord" que es el que relaciona o hace de puente
entre el sistema relacional y el sistema orientado a objetos.

Basándose en algunas de las ideas de Rails y otras propias han surgido bastantes
herramientas de desarrollo de aplicaciones web con una orientación similar: poco
código, reusable, etc.

En este artículo presentaremos Django, que recoge muchas de las ideas de Rails
y aporta algunas soluciones propias. Desarrollaremos una aplicación viendo los
problemas que nos encontramos y cómo los solucionamos. En casi todos los
tutoriales que hemos leído, se presenta sólo lo más básico, pero a la hora de

1 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

avanzar o tratar de hacer algo más "real" nos encontramos con dificultades. Este
artículo trata de paliar ésto.

Requisitos

Para seguir este tutorial es necesario conocer el lenguaje Python, y haber leído
el tutorial de Django. Por supuesto, asumimos que el lector sabe HTML y
tecnologías relacionadas (protocolo HTTP, CSS, etc.)

El ecosistema de Django

Es bastante habitual en este mundillo de los "framework MVC - que te cagas" (2)
que haya una (sana) competencia entre las distintas herramientas y lenguajes.
Podemos encontrar numerosas comparativas, tutoriales, guías, etc, pero todo este
(útil) material sólo rasca la superficie de lo que supone trabajar con estas
herramientas.

A veces da la impresión de que hay un concurso del tipo ¡Con XXX monto una
aplicación del tipo YYY en ZZZ minutos ! ó ¡Mi framework lava más blanco!

No vamos a entrar en el juego. No hemos cronometrado lo que se ha tardado en


terminar el ejemplo que desarrollaremos en este artículo. Si contamos líneas de
código del ejemplo, se podría "picar" todo en apenas diez minutos, pero no este
tiempo es un dato real ni válido. Tampoco vamos a decir que Django es mejor que
otras herramientas (ni siquiera lo tenemos claro), aunque sí que mencionaremos
qué es lo que nos ha gustado y lo que no nos ha gustado (3, 4).

Como bien es sabido, en el mundillo Python siempre hay mucho donde


elegir: ¿Interfaces gráficas? ¿Servidores web? ¿Sistemas de plantillas? ¿...?

Esto puede resultar confuso, puesto que antes de empezar a desarrollar una
aplicación del tipo que sea hay que documentarse bastante para elegir la
herramienta adecuada. En cuanto a los " Web Frameworks" (otra vez la palabreja
;-) también hay bastantes alternativas. Las más conocidas son Django, TurboGears y
Pylons.

Los programadores del lenguaje Ruby no tienen que estrujarse tanto la cabeza.
La herramienta por antonomasia para desarrollo web de Ruby es Ruby On Rails. No
hay mucho más donde elegir. Esto tiene ventajas (centralización de esfuerzos,
uniformidad, ...) e inconvenientes (menor flexibilidad, ...). Cada uno debe valorar
qué es lo que prefiere.

Por último, un breve apunte sobre los lenguajes y sus modismos. Ruby es un
lenguaje con una filosofía parecida a Perl: "hay más de una forma de hacerlo",
Python tiene una aproximación diferente: "hacer las cosas de una sóla manera, la
más sencilla". De nuevo, aquí intervienen las preferencias personales de cada uno a
la hora de programar. Django sigue bastante la " filosofía pythonera" y tratan de

2 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

seguir una serie de principios de diseño (mejor explícito que implícito, asumir que
el desarrollador sabe lo que está haciendo, ...).

Estructura de (una aplicación) Django


Django distingue entre proyectos y aplicaciones. Un proyecto es un sitio web
completo que constar de una o varias aplicaciones. Estas aplicaciones las
proporciona Django o las escribe el desarrollador. El comando que crea un
proyecto es django-admin.py . No vamos a repetir lo que cuenta el tutorial de Django.
Simplemente, con django-admin.py startproject miweb se crea un directorio miweb que
contiene varios ficheros .py : __init__.py , manage.py , settings.py y urls.py .

__init__.py : Define nuestro directorio como un módulo Python válido.


manage.py :Utilidad para gestionar nuestro proyecto: arrancar servidor de
pruebas, sincronizar modelos, etc.
settings.py : Configuración del proyecto.
urls.py : Gestión de las urls. Este fichero sería el controlador de la aplicación.
Mapea las url entrantes a funciones Python definidas en módulos.

Para crear una aplicación nueva dentro del proyecto ejecutamos python manage.py
startapp miaplicacion .
Este comando crea el directorio miaplicacion y los
ficheros __init__.py , views.py , y models.py .

__init__.py :Define nuestro directorio como un módulo Python válido.


models.py : Aquí se definen los modelos u objetos que serán mapeados a una
base de datos relacional.
views.py : Define las funciones que van a responder a las urls entrantes.

Esto es un diseño MVC: modelo ( models.py ), vista ( views.py ), controlador( urls.py ).

Aclaración: los desarrolladores de Django llaman a su arquitectura MVT: Model


- View - Template, ya que consideran que el controlador es el propio framework.

Nuestra aplicación web: Trivial trivial


Vamos a desarrollar una aplicación web un poco más completa que la que
proponen en el tutorial de Django. Es un Trivial multiusuario.

Especificaciones:

Las preguntas y los usuarios los crea un administrador.


Existen diferentes categorías de preguntas.
Cada usuario tiene su propio juego (esto es, responde a sus preguntas).
Es obligatorio estar validado en el sistema para jugar.

Como es una aplicación de prueba, usaremos el servidor de desarrollo que viene


con Django. Los ficheros estáticos (CSS, imágenes, etc) también los servirá Django,
aunque esta práctica está totalmente desaconsejada en un entorno de producción.

3 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Como sistema relacional usaremos sqlite (hay un "driver" para Python).

Nos encontramos en este punto con un enfoque totalmente diferente al de Rails:


Django mantiene los modelos relacionales (tablas, relaciones, ...) a partir del
modelo que nosotros definimos (en una clase), mientras que Rails "adivina" el
modelo a partir del esquema relacional. La ventaja del "enfoque Rails" es que en
cuanto que el modelo cambia, la herramienta detecta estos cambios y se refleja
automáticmente. El inconveniente es que hay que seguir las convenciones Rails
para que ésto funcione.

Personalmente, preferimos el planteamiento de Django: el desarrollador define


modelos, la herramienta se encarga de traducir estos modelos a SQL, pero hay un
inconveniente: si los modelos cambian, hay que hacer el cambio manualmente en
el esquema del sistema relacional. Parece que en posteriores versiones de Django
tratarán de implementar esta mejora, pero a día de hoy (Django versión 0.96), no
es así.

Tras esta breve disquisición, pasemos a definir los modelos. Encontramos las
siguientes entidades:

Usuario, caracterizado por un nombre, "login", contraseña, ...


Categoría
Pregunta, con un título, conjunto de respuestas posibles, respuesta correcta,
un gráfico asociado, ... (5)
Respuesta, asociada a un usuario concreto y una pregunta concreta,
guardando el resultado (acierto/fallo), etc.

Creación del proyecto y la aplicación


Lo primero es crear el proyecto: django-admin.py startproject Trivial

Ajustamos algunos parámetros en settings.py y urls.py . Habilitaremos la interfaz


6
administrativa ( ), el directorio desde el que se sirven los contenidos estáticos y

4 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

algunos ajustes más.

settings.py (extracto):

MEDIA_ROOT = '/home/david/desarrollo/Trivial/site_media/'
MEDIA_URL = 'http://localhost:8000/site_media/'
ADMIN_MEDIA_PREFIX = '/media/'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
'Trivial.juego',
)

urls.py (extracto):

from settings import MEDIA_ROOT


urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
)
urlpatterns += patterns('django.views',
(r'^site_media/(.*)$', 'static.serve', {'document_root': MEDIA_ROOT}),
)

Cuando queramos pasar a producción, sólo tendremos que eliminar la última


entrada en urls.py y editar MEDIA_URL en settings.py .

También tenemos que crear la base de datos sqlite (comando sqlite data/datos.db ).

Ahora, desde el directorio Trivial (directorio raíz) creamos la aplicación


propiamente dicha (juego): python manage.py startapp juego .

Definiendo los modelos


Editamos el fichero juego/models.py para definir nuestros objetos. Las clases que
representan modelos deben heredar de la clase Model y siguen una sintaxis muy
sencilla e intuitiva.

Django incorpora en el paquete django.contrib.auth todo un sistema de


autentificación y gestión de usuarios, así que no vamos a reinventar la rueda y
utilizaremos este sistema (7).

Estos son nuestros modelos:

from django.db import models


from django.contrib.auth.models import User

class Usuario(User):
def __str__(self):
return self.username

5 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

class Admin:
pass

class Categoria(models.Model):
nombre = models.CharField("Categoría", maxlength=200)

def __str__(self):
return self.nombre

class Admin:
pass

class Pregunta(models.Model):
categoria = models.ForeignKey(Categoria, verbose_name="Categoría la que pertenece")
titulo = models.CharField("Título", maxlength=200)
texto = models.TextField("Texto de la pregunta")
respuesta_1 = models.CharField(maxlength=200)
respuesta_2 = models.CharField(maxlength=200)
respuesta_3 = models.CharField(maxlength=200)
respuesta_4 = models.CharField(maxlength=200)
respuesta_correcta = models.CharField(maxlength=200)
foto = models.CharField(maxlength=200)

def __str__(self):
return self.titulo

class Admin:
pass

class Respuesta(models.Model):
tiempo = models.IntegerField("Tiempo en segs.")
resultado = models.IntegerField("0 -> incorrecto, 1 -> correcto")
pregunta = models.ForeignKey(Pregunta, verbose_name="Pregunta que se responde")
usuario = models.ForeignKey(User, verbose_name="Usuario que responde")

def __str__(self):
return str(self.pregunta) + " (Usuario: " + str(self.usuario) + ")"

class Admin:
pass

Como decíamos antes, "mejor explícito que implícito". Definimos un método


__str__en todas las clases para tener una descripción "humana" de cada objeto,
tanto a la hora de desarrollar como de gestionar en la interfaz administrativa. La
clase anidada Admin sirve para que la clase madre aparezca en la interfaz
administrativa.

La clase Usuario hereda directamente de la clase User de Django


(django.contrib.auth.models.User).

Por último, haremos que Django sincronice la información que tiene de los
modelos con el sistema relacional (vamos, que cree las tablas necesarias): python
manage.py syncdb Este comando también creará las tablas necesarias para la aplicación
administrativa y el sistema de gestión de usuarios (de hecho nos pedirá los datos

6 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

necesarios para crear un "superusuario"). Si arrancamos el servidor y apuntamos


nuestro navegador a http://localhost:8000/admin/ veremos en marcha la interfaz de
administración:

Lo primero que hemos hecho ha sido crear un grupo (Concursantes) y asignarle


el permiso de "crear objetos del tipo Respuesta". Después creamos unos cuantos
usuarios y les hacemos miembros del grupo. Ya tenemos un sistema de control de
acceso, permisos bastante granulares (estos usuarios sólo podrán crear objetos del
tipo Respuesta, pero no modificarlos o borrarlos) sin escribir nada de código.

Siguente: implementando la autentificación


El siguiente paso es relativamente sencillo si utilizamos las facilidades que
Django nos proporciona. El decorador @login_required en el paquete
django.contrib.auth.decorators funciona de la siguiente manera: si el usuario
no está autentificado, redirige a una plantilla o template de validación
(registration/login.html por defecto):

7 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Si está autentificado, la función "decorada" ( index en este caso) se ejecuta


normalmente.

La primera pantalla que queremos que el usuario autenfificado vea es un listado


de preguntas clasificado por categorías. Éste sería nuestro "index.html", pero,
como hemos dicho, queremos que el usuario se valide antes. Veamos cómo hacerlo.

En urls.py añadimos una entrada para "mapear" la dirección "/" (raíz del sitio) a
la función " index " en views.py :

urls.py (extracto):

from settings import MEDIA_ROOT


urlpatterns = patterns('',
(r'^/?$', 'Trivial.juego.views.index'),
(r'^admin/', include('django.contrib.admin.urls')),
)
urlpatterns += patterns('django.views',
(r'^site_media/(.*)$', 'static.serve', {'document_root': MEDIA_ROOT}),
)

Y nuestra función ( 8) en views.py sería algo así:

@login_required
def index(request):
categorias = Categoria.objects.all()
preguntas = Pregunta.objects.all()
respuestas = Respuesta.objects.filter(usuario=request.user)
return render_to_response('index.html',
{'categorias': categorias,
'preguntas': preguntas,
'respuestas': respuestas,
'usuario': request.user,}
)

¿Qué hace este index ? Recoge todas las categorías, preguntas y respuestas del
usuario validado y se las "pasa" a una plantilla o template llamada " index.html ".

8 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

También le pasa los datos del usuario (request.user). Como hemos especificado que
hay un login previo, podemos estar seguros de que esta variable "usuario" tiene
datos correctos.

Veamos ahora la plantilla o template index.html , no sin antes repasar cómo


funcionan los templates en Django:

{% extends "base.html" %}

{% block cuerpo %}

<strong>Listado de preguntas</strong>
{% if categorias %}
{% regroup preguntas by categoria as agrupado %}
<ul>
{% for grupo in agrupado %}
<li>{{ grupo.grouper }}</li>
<ul>
{% for item in grupo.list %}
<li><a href="pregunta/{{item.id}}/">{{ item.titulo }}</a><br>
{% for r in respuestas %}
{% ifequal item r.pregunta %}
&nbsp;&nbsp;La pregunta ya ha sido respondida.
{% endifequal %}
{% endfor %}
</li>
{% endfor %}
</ul>
{% endfor %}
</ul>
{% else %}
<p>No hay categorías</p>
{% endif %}

<p><a href="/accounts/logout/">Desconectar</a></p>

{% endblock %}

En este template comprobamos si hay categorías {% if categorias %} y mostramos


en forma de listas anidadas todas las preguntas de cada categoría con la etiqueta
{% regroup preguntas by categoria as agrupado %} y lo que sigue. Para cada pregunta
comprobamos si tiene una respuesta asociada:

{% for r in respuestas %}
{% ifequal item r.pregunta %}
&nbsp;&nbsp;La pregunta ya ha sido respondida.
{% endifequal %}
{% endfor %}

Esta comprobación es algo ineficiente (en cada pregunta itera sobre todas las
respuestas) pero no lo hemos refinado por mantener la simplicidad. Seguro que se
puede hacer mejor ;-)

En este template también estamos utilizando una característica muy útil: la


herencia de plantillas. En una plantilla aparte ( base.html ) definimos un esqueleto

9 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

con unos bloques de contenido que cada una de las plantillas "hijas" se encarga de
completar con {% block loquesea %}

Así quedaría nuestra pantalla inicial:

Formulario de preguntas
Cuando el usuario sigue el enlace ( <a href="pregunta/{{item.id}}/">{{ item.titulo }}</a> )
que presenta cada pregunta en la plantilla index.html se le dirige a la página que
llamaremos "ficha de pregunta". Estas son las modificaciones que hemos
introducido:

urls.py (extracto):

urlpatterns = patterns('',
(r'^/?$', 'Trivial.juego.views.index'),
(r'^pregunta/(\d+)/$', 'Trivial.juego.views.pregunta'),
(r'^admin/', include('django.contrib.admin.urls')),
)

En views.py definimos la función "pregunta":

from django.shortcuts import render_to_response


from django.contrib.auth.decorators import login_required
from Trivial.juego.models import Pregunta, Respuesta
@login_required
def pregunta(request, id):
pregunta = Pregunta.objects.get(id=id)
try:

10 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

respuesta = Respuesta.objects.get(pregunta=id, usuario=request.user)


except ObjectDoesNotExist:
respuesta = None
return render_to_response('pregunta.html',
{'pregunta': pregunta,
'respuesta': respuesta,
'tiempo': str(int(time.time())),
}
)

A la función pregunta le llegan dos argumentos: request e id , tal y como se define


en urls.py . Lo primero que hacemos es buscar la pregunta correspondiente ( pregunta
= Pregunta.objects.get(id=id) ) y luego buscamos la posible respuesta que haya podido
hacer el usuario en una anterior visita ( respuesta = Respuesta.objects.get(pregunta=id,
usuario=request.user) ). Si no hay respuestas capturamos la excepción, asignamos None
a la respuesta y seguimos.

Finalmente, ésta es la plantilla que muestra los datos de una pregunta,


pregunta.html :

{% extends "base.html" %}

{% block cuerpo %}

<h2>Categoría: {{ pregunta.categoria }}</h2>


<h3>{{ pregunta.titulo }}</h3>

{% if texto_error %}
<p class="error">{{ texto_error }}</p>
{% endif %}

<img class="foto" src="/site_media/{{ pregunta.foto }}">

<p>{{ pregunta.texto }}</p>

{% if respuesta %}
<p>Ya has respondido antes a la pregunta.</p>
<p>Tiempo empleado: {{ respuesta.tiempo }} segundos.</p>
<p>El resultado fue
{% if respuesta.resultado %}
CORRECTO
{% else %}
INCORRECTO
{% endif %}
</p>
{% else %}
<form method="post" action="/responder/">
<input type="hidden" name="pregunta" value="{{ pregunta.id }}">
<input type="hidden" name="tiempo" value="{{ tiempo }}">
<input type="radio" value="{{ pregunta.respuesta_1 }}"
name="respuesta">{{ pregunta.respuesta_1 }}<br>
<input type="radio" value="{{ pregunta.respuesta_2 }}"
name="respuesta">{{ pregunta.respuesta_2 }}<br>
<input type="radio" value="{{ pregunta.respuesta_3 }}"
name="respuesta">{{ pregunta.respuesta_3 }}<br>
<input type="radio" value="{{ pregunta.respuesta_4 }}"
name="respuesta">{{ pregunta.respuesta_4 }}<br>

11 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

<br>
<input type="submit" value="Responder">
</form>
{% endif %}

{% endblock %}

Nos encontramos en esta plantilla con una variable ( texto_error ) que no hemos
asignado desde la función pregunta . Esta variable puede tener un valor cuando esta
plantilla es invocada desde otra función definida en views.py ( respuesta ). Lo veremos
un poco más adelante.

Lo primero que comprobamos es si esta pregunta ya ha sido respondida. Si es


así, la variable respuesta tendrá un valor distinto a None. En este caso informamos
al usuario del resultado y el tiempo empleado en resolver la pregunta.

Si no hay respuesta, generamos un formulario con las posibles respuestas y dos


campos ocultos con el id de la pregunta y una marca de tiempo. El formulario
apunta a la url /responder/ , ahora veremos cómo lo tratamos.

12 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Respondiendo a la pregunta
De nuevo, añadimos una regla al fichero urls.py para procesar las respuestas de
los usuarios. El fichero quedaría así (versión final):

from django.contrib.auth.views import login, logout


from django.conf.urls.defaults import *
from settings import MEDIA_ROOT

urlpatterns = patterns('',
(r'^/?$', 'Trivial.juego.views.index'),
(r'^pregunta/(\d+)/$', 'Trivial.juego.views.pregunta'),
(r'^responder/$', 'Trivial.juego.views.respuesta'),
(r'^accounts/login/$', login),
(r'^accounts/logout/$', logout, {'template_name': 'registration/logout.html' }),
(r'^admin/', include('django.contrib.admin.urls')),
)
urlpatterns += patterns('django.views',
(r'^site_media/(.*)$', 'static.serve', {'document_root': MEDIA_ROOT}),
)

La función nueva (respuesta) se define en views.py y es así:

@login_required
def respuesta(request):
pregunta = Pregunta.objects.get(id=request.POST['pregunta'])
if not request.POST.has_key('respuesta') or request.POST['respuesta'] == "":

13 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

texto_error = "Debe elegir una opción"


return render_to_response('pregunta.html',
{'pregunta': pregunta,
'texto_error': texto_error,
'tiempo': str(int(time.time())),
}
)
else:
opcion = request.POST['respuesta'];
respuesta = Respuesta()
respuesta.pregunta = pregunta
respuesta.usuario = request.user
respuesta.tiempo = int(time.time()) - int(request.POST['tiempo'])
if pregunta.respuesta_correcta == opcion:
respuesta.resultado = 1
else:
respuesta.resultado = 0
respuesta.save()
return render_to_response('respuesta.html',
{'pregunta': pregunta,
'respuesta': respuesta,
'opcion': opcion,
}
)

Primero localizamos la pregunta (nos llega el id en la variable POST ' pregunta ').
Después comprobamos que han pulsado uno de los "radiobutton" de respuesta
( request.POST['respuesta'] ). Si no han respondido, redirigimos de nuevo a la página de
pregunta pasando un mensaje de error.

14 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Si han respondido, creamos un objeto Respuesta asociado a la pregunta y al


usuario. También asignamos a esta respuesta el tiempo que se ha tardado en
resolver la pregunta y el resultado. Después, redirigimos a la plantilla
'respuesta.html' pasando el objeto pregunta, el objeto respuesta recién creado y la
opción que habían seleccionado.

respuesta.html :

{% extends "base.html" %}

{% block cuerpo %}

<h2>Resultado de la pregunta</h2>
<h3>{{ pregunta.titulo }}</h3>
<img class="foto" src="/site_media/{{ pregunta.foto }}">

<p>{{ pregunta.texto }}</p>


<p>Respuesta seleccionada: {{ opcion }}</p>
<p>Respuesta correcta: {{ pregunta.respuesta_correcta }}</p>
{% if respuesta.resultado %}
<p>¡Enhorabuena!</p>
{% else %}
<p>¡Has fallado!</p>
{% endif %}
<p>Tiempo empleado: {{ respuesta.tiempo }} segundos.</p>
{% endblock %}

15 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Sencillo, simplemente mostramos los datos del objeto respuesta, la pregunta


asociada y lo que el usuario respondió.

Conclusiones
Hemos hecho una aplicación web muy básica y sencilla, pero demuestra que
muchas tareas complicadas y/o tediosas de implementar nos la proporciona la
herramienta Django. La interfaz administrativa y el sistema de
autentificación nos han salido "gratis". Probablemente, la implementación de
estas dos funcionalidades nos hubiesen llevado bastante tiempo.
Observamos también la extrema sencillez en el desarrollo: con cuatro
elementos con unas funciones muy concretas (urls, modelos, vistas y
plantillas) tenemos perfectamente separadas la lógica, los datos y la
presentación. Compárese esta simplicidad con la típica aplicación J2EE, por
sencilla que sea. No hay color. Que las soluciones basadas en J2EE sean más
"potentes", escalables, robustas, etc. no lo voy a negar. Pero, ¿acaso se
necesita siempre esa "potencia"?.
No hemos desarrollado una aplicación similar con Rails, por lo que no sería
muy justo decir que Django es más fácil o mejor. Lo que si que podemos decir,
por lo que hemos visto y leído es que Django aporta varias características que
ahorran mucho trabajo, en este caso la interfaz administrativa y el sistema de
autentificación ( 9).

16 de 17 26/08/10 13:15
T utorial de Django http://davidasorey.net/static/django-tutorial/

Notas
1. Estoy un poco cansado de la palabra "framework". A partir de ahora y en lo
que queda de tutorial voy a emplear el término "herramienta", aunque no sea
el más adecuado ;-)
2. Disculpen el lenguaje soez, a veces se me escapa alguna palabrota ;-)
3. La documentación que he utilizado son estas dos fuentes: la documentación de
Django y el libro "The Django Book".
4. Una de las cosas que más me ha gustado de Django es la documentación:
completa, accesible y, sobre todo, centralizada. Me gusta mucho más que,
por ejemplo, la documentación de Rails: tutoriales dispersos por internet, falta
de un índice por tópicos, ... No voy a ser malpensado, pero da la impresión
que lo que quieren es que compres el libro que ha escrito el autor de Rails.
5. No voy a ser muy estricto con cuestiones de normalización del diseño de la
base de datos. Probablemente sería mejor tener una tabla aparte para las
posibles respuestas con una clave apuntando a la pregunta. Mantendremos
este diseño (incorrecto) por sencillez.
6. Es una aplicación web muy bien terminda y personalizable, nada que ver con
el "scaffold" básico que nos puede proporcionar Ruby On Rails. Si una
aplicación requiere una interfaz administrativa para manejar los distintos
objetos en Rails hay que programarla. Django nos la da ya hecha.
7. Rails por defecto no tiene nada similar, aunque existe un "plugin" para Rails
que implementa un sistema de autentificación. No lo he utilizado, así que no
puedo valorarlo.
8. Función, no método. Intencionadamente, los diseñadores de Django han
decidido que no hay necesidad de lidiar con objetos para atender a una simple
petición.
9. Rails también proporciona un montón de funciones, atajos y utilidades que
ahorran tiempo (la primera que se me viene a la cabeza es la maravillosa
options_from_collection_for_select).
10. Rollo legal: este es un documento de libre difusión (licencia Creative
Commons "by-nc-sa") con algunas limitaciones. Leer el texto de la licencia
completo para más detalles.

Subir

(cc) David Asorey Álvarez


Mayo de 2007
David.Asorey.Alvarez@gmail.com

17 de 17 26/08/10 13:15

Potrebbero piacerti anche