Contenido
Trabajo en proceso, espera cambios frecuentes. Tu ayuda y retroalimentación son bienvenidos. Ver página de charlas. |
Contenido
Evolución del desarrollo web
- Páginas HTML estáticas
- CGI: código para generar páginas web dinámicas:
- Código embebido en páginas web (PHP, JSP, ASP, ...)
- Frameworks web:
- RoR, Struts, Symphony
- Django, Pylons, Web2Py
Django
Django permite a los desarrolladores crear de forma rápida sitios web de altas prestaciones basados en información almacenada en bases de datos bajo el principio de no repetición (Do Not Repeat Yourself: DRY).
El nombre
Adrian Holovaty, co-creador de Django, es un guitarrista inspirado por Django Reinhardt.
MVC / MVT
MTV: Desarrollo web según un patrón Modelo - Vista - Template (similar al patrón MVC)
- Modelo: capa de Datos. Describe los datos que gestiona la aplicación. Cada modelo enlaza una tabla en la base de datos.
- Vista: capa de Negocio. Describe a qué datos hay que acceder y los transforma.
- Template (plantillas): capa de Presentación. Describe cómo se van a presentar los datos al usuario.
Instalación
https://docs.djangoproject.com/en/1.3/intro/install/
>>> import django >>> django.VERSION (1, 3, 0, 'final', 0)
Crear un proyecto
Seguimos el tutorial de django: https://docs.djangoproject.com/en/1.3/intro/tutorial01/
$ django-admin.py startproject sitio_encuestas $ ls -l sitio_encuestas/ __init__.py manage.py settings.py urls.py
- __init__.py
- Indica que se trata de un paquete.
- manage.py
- Programa de gestión de django. A partir de ahora será el que usemos para interactuar con el proyecto.
- settings.py
- Fichero de configuración del proyecto.
- urls.py
- Gestiona la tabla de urls a las que responde el proyecto.
Servidor de desarrollo
Comprobamos el funcionamiento:
$ cd sitio_encuestas $ python manage.py runserver Validating models... 0 errors found Django version 1.3, using settings 'sitio_encuestas.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
Comprobamos la dirección con el navegador o
$ curl -I 127.0.0.1:8000 HTTP/1.0 200 OK Date: Mon, 22 Aug 2011 20:33:33 GMT Server: WSGIServer/0.1 Python/2.7.1+ Content-Type: text/html
Este servidor ligero nos servirá para desarrollar el proyecto. No está pensado para sitios en producción.
$ python manage.py runserver 8080
y También la ip:
$ python manage.py runserver 0.0.0.0:8000
Configuración del proyecto
Editar settings.py Como el fichero necesita rutas absolutas, podemos añadir esta función:
import os def ruta_abs(x): return os.path.join(os.path.abspath(os.path.dirname(__file__)), x)
Configuración de la base de datos
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 'NAME': '', # Or path to database file if using sqlite3. 'USER': '', # Not used with sqlite3. 'PASSWORD': '', # Not used with sqlite3. 'HOST': '', # Set to empty string for localhost. Not used with sqlite3. 'PORT': '', # Set to empty string for default. Not used with sqlite3. } }
Para usar sqlite:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'. 'NAME': ruta_abs('encuestas.db'), # Or path to database file if using sqlite3. } } <source> Cambiamos también otros datos: <source lang="python"> TIME_ZONE = 'Europe/Madrid' LANGUAGE_CODE = 'es-es'
Ejecutamos:
$python manage.py syncdb
que crea las tablas necesarias para el desarrollo de proyecto, incluyendo todas las aplicaciones incuidas en INSTALLED_APPS
Proyectos y aplicaciones
Para optimizar los recursos, un proyecto puede tener varias aplicaciones. Estas aplicaciones se pueden instalar en varios proyectos. Por eso se dice que las aplicaciones de django son "pluglables".
$ python manage.py startapp encuestas
Esto creará el siguiente directorio:
encuestas/
__init__.py
models.py
views.py
Hay que añadir la nueva apliación a INSTALLED_APPS dentro de settings.py
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.messages', 'sitio_encuestas.encuestas' )
Definición de modelos
models.py
from django.db import models class Encuesta(models.Model): pregunta = models.CharField(max_length=200) fecha_pub = models.DateTimeField(u'fecha de publicación') def __unicode__(self): return self.pregunta class Opcion(models.Model): encuesta = models.ForeignKey(Encuesta) opcion = models.CharField(max_length=200) votos = models.IntegerField() def __unicode__(self): return self.opcion
$ python manage.py sql encuestas
Esto hará que veamos el siguiente código SQL:
BEGIN; CREATE TABLE "encuestas_encuesta" ( "id" INTEGER NOT NULL PRIMARY KEY, "pregunta" VARCHAR(200) NOT NULL, "fecha_pub" datetime NOT NULL ) ; CREATE TABLE "encuestas_opcion" ( "id" INTEGER NOT NULL PRIMARY KEY, "encuesta_id" INTEGER NOT NULL REFERENCES "encuestas_encuesta" ("id"), "opcion" VARCHAR(200) NOT NULL, "votos" INTEGER NOT NULL ) ; COMMIT;
Si el código es correcto, ejecutamos:
$ python manage.py syncdb Creating table encuestas_encuesta Creating table encuestas_opcion You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (Leave blank to use 'lm'): lm E-mail address: lm@micorreo.com Password: Password (again): Superuser created successfully. Installing custom SQL ... Installing indexes ... No fixtures found.
Jugando con el ORM de Django
$ python manage.py shell
>>> from encuestas.models import Encuesta, Pregunta # Importa las clases del modelo # No hay encuestas >>> Encuesta.objects.all() [] # Creamos una nueva encuesta >>> import datetime >>> p = Encuesta(pregunta="¿Cómo va el curso?", fecha_pub=datetime.datetime.now()) # Guardamos el objeto en la base de datos >>> p.save() # Creación de ID automática >>> p.id 1 # Acceso a los valores >>> p.pregunta "¿Cómo va el curso?" >>> p.fecha_pub datetime.datetime(2011, 7, 15, 12, 00, 53) # Cambio de valores de los atributos >>> p.pub_date = datetime.datetime(2011, 7, 20, 0, 0) >>> p.save() # objects.all() muestra todas las encuestas de la base de datos >>> Encuesta.objects.all() [<Encuesta: ¿Cómo va el curso?]
Vemos el contenido de la encuesta porque hemos añadido el método __unicode__. Si no, veríamos <Encuesta: Encuesta object> Se crea el método __unicode__ y no __str__ porque los modelos de Django tratan con unicode por defecto.
# API de búsquedas de Django >>> Encuesta.objects.filter(id=1) [<Encuesta: ¿Cómo va el curso?>] >>> Encuesta.objects.filter(pregunta__startswith='¿Cómo') [<Encuesta: ¿Cómo va el curso?>] # Obtener las encuestas de 2011 >>> Encuesta.objects.get(fecha_pub__year=2011) <Encuesta: ¿Cómo va el curso?> >>> Encuesta.objects.get(id=2) Traceback (most recent call last): ... DoesNotExist: Encuesta matching query does not exist. # Búsqueda por clave primaria >>> Encuesta.objects.get(pk=1) <Encuesta: ¿Cómo va el curso?> # Vamos a insertar unas opciones para ver cómo funcionan las relaciones. # Podemos crear las opciones desde la misma encuesta: >>> p = Encuesta.objects.get(pk=1) # Opciones relacionadas con nuestra encuesta: >>> p.opcion_set.all() [] # Creamos tres opciones >>> p.opcion_set.create(opcion='Muy bien', votos=0) <Opcion: Muy bien> >>> p.opcion_set.create(opcion='Bien', votos=0) <Opcion: Bien> >>> c = p.opcion_set.create(opcion='Regular', votos=0) # Los objetos Opción tienen acceso desde la API a la encuesta a la que pertenecen: >>> c.encuesta <Encuesta: ¿Cómo va el curso?> # Y viceversa. Los objetos Encuesta acceden a sus Opciones: >>> p.opcion_set.all() [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] >>> p.opcion_set.count() 3 # La API sigue de forma automática las relaciones. # Para separar las relaciones se usan dobles guiones bajos. # Busca todas las Opciones para cualquier encuesta publicada en 2011 >>> Opcion.objects.filter(encuesta__fecha_pub__year=2011) [<Opcion: Muy bien>, <Opcion: Bien>, <Opcion: Regular>] # Elimina una de las opciones: >>> c = p.opcion_set.filter(opcion__startswith='Regular') >>> c.delete()
Otros métodos en los modelos
Podemos añadir métodos normales a los modelos:
import datetime class Encuesta(models.Model): #... def publicada_hoy(self): return self.fecha_pub.date() == datetime.date.today()
Y podemos usarlos así:
>>> p = Escuesta.objects.get(pk=1) >>> p.publicada_hoy() False
Más información sobre las relaciones entre modelos: Acceder a objetos relacionados. Para más infor sobre cómo usar los dobles guiones bajos para hacer búsquedas por campos mediante la API: búsquedas mediante los campos Para más detalles sobre la API de la base de datos: Referencia de la Base de Datos.
El poderoso Admin de Django
- El Admin es una herramienta pensada para el "backend", no para el acceso de los usuarios
- Simplifica la tarea de insertar, modificar y eliminar contenido de la web.
Activar el Admin
- Por defecto está desactivado.
- Añade django.contrib.admin a la lista de INSTALLED_APPS en settings.py.
- Ejecuta
$ python manage.py syncdb
- Edita el fichero urls.py de tu proyecto y descomenta las líneas que hacen referencia al admin (3 líneas en total)
El fichero tiene que quedar al final algo así:
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below and add 'django.contrib.admindocs'
# to INSTALLED_APPS to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
)