Curso Python DGA 2011/django/intro

De WikiEducator
< Curso Python DGA 2011‎ | django
Revisión a fecha de 22:42 24 ago 2011; Lmorillas (Discusión | contribuciones)

(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Saltar a: navegación, buscar

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.

Icon present.gif
Tip: Podemos cambiar el puerto ejecutando:
 $ 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.