Curso Python DGA 2011/django/intro
Contenido
Instalación
- Comprobamos que está instalado (y la versión)
>>> import django >>> django.VERSION (1, 3, 0, 'final', 0)
Creación de un proyecto
$ django-admin.py startproject sitio_encuestas $ ls -l sitio_encuestas/ __init__.py manage.py settings.py urls.py
Un proyecto en Django son 4 ficheros:
- __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 web de desarrollo
El proyecto incorpora un servidor web:
$ 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
$ python manage.py runserver 8080
y También la ip:
$ python manage.py runserver 0.0.0.0:8000
Este servidor ligero nos servirá para desarrollar el proyecto. No está pensado para sitios en producción.
Para usar Django en producción, revisa la documentación: https://docs.djangoproject.com/en/1.3/howto/deployment/
Configuración del proyecto
Editar settings.py
Rutas absolutas
Como la configuración necesita rutas absolutas, podemos añadir esta función a settings.py:
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
Por defecto, tiene sopote para Postgresql, MySQL, Sqlite y Oracle.
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> Para usar otra base de datos, tenemos que configurar el servidor con una base de datos y un usuario que tenga acceso a ella. ===configuración regional=== <source lang="python"> TIME_ZONE = 'Europe/Madrid' LANGUAGE_CODE = 'es-es'
Aplicar los cambios
$python manage.py syncdb
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".
Creación de una aplicación
$ python manage.py startapp encuestas
Esto creará el siguiente directorio:
encuestas/
__init__.py
models.py
views.py
Incluir la aplicación en el proyecto
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
- Tipos de datos: https://docs.djangoproject.com/en/1.3/ref/models/fields/
- Más opciones
Ver sql
$ 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;
Syncdb
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.
Si las tablas tienen datos, ya no modificará la estructura. Soluciones: eliminar los datos de esa aplicación o usar South: http://south.aeracode.org/
Acceso a los datos
$ 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.