el web framework para perfeccionistas con límites de tiempo
sudo apt-get update
sudo apt-get install python-setuptools python-dev build-essential git-core -y
sudo easy_install pip
sudo pip install virtualenv
sudo pip install virtualenvwrapper
cd ~
mkdir ~/.virtualenvs
echo 'export WORKON_HOME=~/.virtualenvs' >> ~/.bashrc
echo 'source /usr/local/bin/virtualenvwrapper.sh' >> ~/.bashrc
echo 'export PIP_VIRTUALENV_BASE=~/.virtualenvs' >> ~/.bashrc
source ~/.bashrc
mkvirtualenv curso
pip install django
# Para desativar el virtualenv:
deactivate
# Para volver a activarlo:
workon curso
# Para eliminar un virtualenv
rmvirtualenv curso
python -c "import django; print(django.get_version())"
django-admin.py startproject curso
Debería haberse creado esta estructura:
curso/
manage.py
curso/
__init__.py
settings.py
urls.py
wsgi.py
El directorio curso/ de más afuera es un contenedor para tu proyecto. El nombre no afecta a Django; lo podés renombrar libremente.
La base de datos por defecto es SQLite
Si se desea utilizar otra base de datos, instalar sus módulos y cambiar lo siguiente:
python manage.py migrate # Desde la carpeta curso de más afuera
python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
October 03, 2014 - 10:27:07
Django version 1.7, using settings 'curso.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Para que escuche desde todas las ips desde el puerto 8000:
python manage.py runserver 0.0.0.0:8000
python manage.py startapp encuestas
encuestas/
__init__.py
models.py
tests.py
views.py
Vamos a crear dos modelos: Pregunta y Eleccion.
Una Pregunta tiene un texto de pregunta y una fecha de publicación.
Una Eleccion tiene dos campos: el texto de la opción y un contador de votos.
Cada Eleccion está asociada a una Encuesta.
Estos conceptos se representan mediante clases Python. Editamos el archivo encuestas/models.py para que se vea así:
# -*- coding: utf-8 -*-
from django.db import models
class Pregunta(models.Model):
texto_pregunta = models.CharField(max_length=200)
pub_date = models.DateTimeField('fecha publicada')
class Eleccion(models.Model):
pregunta = models.ForeignKey(Pregunta)
texto_opcion = models.CharField(max_length=200)
votos = models.IntegerField(default=0)
Más acerca de campos en Model Field Reference
Ese poquito código le da a Django un montón de información. A partir de él, Django puede:
Primero debemos informarle a nuestro proyecto que la app encuestas está instalada.
Las apps Django son “pluggables”: podés usar una app en múltiples proyectos, y distribuirlas, porque no necesitan estar atadas a una instancia de Django particular.
Editamos de nuevo el archivo settings.py, y cambiamos el setting INSTALLED_APPS para incluir 'encuestas'. Se verá algo así:
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'encuestas',
)
Ahora Django sabe sobre nuestra app polls.
Corramos otro comando:
python manage.py makemigrations encuestas
Con esto le estás diciendo a django que has hecho modificaciones a tus models
Migrations es con lo que Django guarda los cambios a tus modelos. Son sólo archivos.
Se pueden leer las migraciones del nuevo modelo: encuestas/migrations/0001_initial.py.
python manage.py sqlmigrate encuestas 0001
Hacemos efectiva nuestra migración
python manage.py migrate
Operations to perform: Apply all migrations: admin, contenttypes, encuestas, auth, sessions Running migrations: Applying encuestas.0001_initial... OK
Obtendriamos algo como esto:
Para invocar el shell de Python, usamos este comando:
python manage.py shell
Usamos esto en lugar de simplemente tipear “python” porque manage.py setea la variable de entorno DJANGO_SETTINGS_MODULE, que le da a Django el import path al archivo settings.py.
Exploramos la API de base de datos:
# Importamos las clases de los modelos que escribimos.
>>> from encuestas.models import Pregunta, Eleccion
# No hay preguntas en el sistema todavía.
>>> Pregunta.objects.all()
[]
# Creamos una nueva Pregunta.
# El soporte para zonas horarias está habilitado por defecto en settings.py
# Django espera entonces un datetime con tzinfo para pub_date.
# Usamos timezone.now() en lugar de datetime.datetime.now()
>>> from django.utils import timezone
>>> q = Pregunta(texto_pregunta="Que hay de nuevo, viejo?", pub_date=timezone.now())
# Guardamos el objeto en la base de datos. Debemos llamar
# a save() explícitamente.
>>> q.save()
# Ahora tiene un ID. Notar que esto puede decir "1L" en lugar de "1",
# dependiendo de la base de datos que se esté usando. Esto sólo significa
# que el backend del motor de base de datos prefiere devolver los enteros
# como long integer de Python.
>>> q.id
1
# Podemos acceder a las columnas de la base de datos como atributos de Python.
>>> q.texto_pregunta
"Que hay de nuevo, viejo?"
>>> q.pub_date
datetime.datetime(2014, 10, 3, 13, 0, 0, 775217, tzinfo=<UTC>)
# Podemos cambiar valores cambiando el valor de los atributos, luego
# llamamos a save().
>>> q.texto_pregunta = "Que te pasa?"
>>> q.save()
# objects.all() muestra todas las preguntas en la base de datos.
>>> Pregunta.objects.all()
[<Pregunta: Pregunta object>]
Un minuto. <Pregunta: Pregunta object> es, definitivamente, una representación poco útil de este objeto. Arreglemos esto editando los modelos (en el archivo encuestas/models.py) y agregando el método __unicode__() a Pregunta y Eleccion:
from django.db import models
class Pregunta(models.Model):
# ...
def __unicode__(self): # __str__ en Python 3
return self.texto_pregunta
class Eleccion(models.Model):
# ...
def __unicode__(self): # __str__ en Python 3
return self.texto_opcion
Usamos __unicode__ en vez de __str__ porque estamos trabajando en python 2, python 3 resuelve las discrepancias entre unicode y str haciendo que todo sea en unicode
Notar que estos son métodos de python normales, podemos agregar los que queramos
import datetime
from django.db import models
from django.utils import timezone
class Pregunta(models.Model):
# ...
def fue_publicada_recientemente(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
Más info de manejos de zonas horarias en la documentación de time zone.
Ejecutamos nuestro shell nuevamente
>>> from encuestas.models import Pregunta, Eleccion
# Confirmemos que __unicode__() funciona.
>>> Pregunta.objects.all()
[<Pregunta: Que te pasa?>]
# Django provee una API de búsqueda muy completa a partir de keywords arguments.
>>> Pregunta.objects.filter(id=1)
[<Pregunta: Que te pasa?>]
>>> Pregunta.objects.filter(texto_pregunta__startswith='Que')
[<Pregunta: Que te pasa?>]
# Obtengamos la Pregunta que se publicó este año.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Pregunta.objects.get(pub_date__year=current_year)
<Pregunta: Que te pasa?>
# Si pedimos por un ID que no existe, se levantará una excepción.
>>> Pregunta.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Pregunta matching query does not exist.
# Buscar por clave primaria es un caso muy común, Django provee un atajo
# para búsquedas exactas por primary-key.
# Lo siguiente es equivalente a Pregunta.objects.get(id=1).
>>> Pregunta.objects.get(pk=1)
<Pregunta: Que te pasa?>
# Confirmemos que el método que agregamos funciona.
>>> q = Pregunta.objects.get(pk=1)
>>> q.fue_publicada_recientemente()
True
# Démosle a la Pregunta un par de Elecciones. La llamada a create crea un nuevo
# objeto Eleccion, ejecuta la sentencia INSERT, agrega la opción al conjunto
# de opciones disponibles y devuelve el nuevo objeto Eleccion. Django crea
# un conjunto para mantener el "otro lado" de la relación dada por ForeignKey
# (e.g., las opciones de la Pregunta) que se puede acceder vía la API.
>>> q = Pregunta.objects.get(pk=1)
# Muestra las opciones relacionadas -- ninguna por ahora.
>>> q.eleccion_set.all()
[]
# Creamos tres opciones.
>>> q.eleccion_set.create(texto_opcion='No mucho', votos=0)
<Eleccion: No mucho>
>>> q.eleccion_set.create(texto_opcion='El cielo', votos=0)
<Eleccion: El cielo>
>>> c = q.eleccion_set.create(texto_opcion=u'Sólo acá, hackeando', votos=0)
# Los objetos Eleccion tienen acceso vía la API a la Pregunta relacionada.
>>> c.pregunta
<Pregunta: Que te pasa?>
# Y vice versa: los objetos Pregunta objects tienen acceso a los
# objetos Eleccion.
>>> q.eleccion_set.all()
[<Eleccion: No mucho>, <Eleccion: El cielo>, <Eleccion: Sólo acá, hackeando>]
>>> q.eleccion_set.count()
3
# La API sigue las relaciones automáticamente tanto como se necesite.
# Se usa doble guión bajo para separar relaciones.
# Esto funciona tantos niveles de profundidad como se quiera; no hay límite.
# Encontremos todas las Elecciones para cualquier Pregunta cuya pub_date es
# este año (reusando la variable 'current_year' que creamos arriba).
>>> Eleccion.objects.filter(pregunta__pub_date__year=current_year)
[<Eleccion: No mucho>, <Eleccion: El cielo>, <Eleccion: Sólo acá, hackeando>]
# Borremos una de las opciones. Para esto usamos delete().
>>> c = q.eleccion_set.filter(texto_opcion__startswith='Sólo acá, hackeando')
>>> c.delete()
Para más información sobre relaciones en modelos, ver Acceder objetos relacionados. Para más detalles sobre cómo usar los doble guión bajo para efectuar búsquedas usando la API, ver Field lookups. Para el detalle completo de la API de base de datos, ver Database API reference.
Tutorial oficial actualizado
Tutorial en español (versión 1.5)
Tango with django (tutorial más completo)
Two Scoops of Django: Best Practices For Django 1.6 (Inglés - Libro impreso o para kindle)
Esta instalación se realiza 1 vez por equipo. Varía sistema a sistema. Esta es para Ubuntu. Reemplazar todos los .bashrc por .bash_profile para OS X
sudo apt-get update
sudo apt-get install python-setuptools python-dev build-essential git-core -y
sudo easy_install pip
sudo pip install virtualenv
sudo pip install virtualenvwrapper
cd ~
mkdir ~/.virtualenvs
echo 'export WORKON_HOME=~/.virtualenvs' >> ~/.bashrc
echo 'source /usr/local/bin/virtualenvwrapper.sh' >> ~/.bashrc
echo 'export PIP_VIRTUALENV_BASE=~/.virtualenvs' >> ~/.bashrc
source ~/.bashrc
Esta instalación se realiza 1 vez por proyecto, si bien cada desarrollador puede tener su propio esquema de trabajo, este es uno de los más usados
mkvirtualenv curso
pip install django
django-admin.py startproject nombreproyecto
Editar el settings.py a nuestro gusto, y luego generar la base de datos:
python manage.py migrate # Desde la carpeta donde está el manage.py
Cada proyecto puede tener 1 o más aplicaciones
python manage.py startapp nombreaplicacion
Desde el archivo models.py replicamos nuestro MER, con nombres de clase para nuestras entidades, y los atributos para nuestros campos
En el models.py, transcribir tu MER a código Django, ver referencia de campos. Para el ejemplo anterior:
# -*- coding: utf-8 -*-
from django.db import models
class Etiqueta(models.Model):
nombre = models.CharField(max_length=200)
class Post(models.Model):
titulo = models.CharField(max_length=200)
texto = models.TextField()
pub_date = models.DateTimeField('fecha publicado')
etiquetas = models.ManyToManyField(Etiqueta)
class Comentario(models.Model):
email = models.EmailField()
comentario = models.TextField()
post = models.ForeignKey(Post)
Agregamos nuestra nueva app a la variable INSTALLED_APPS de nuestro settings.py
Creamos nuestra migración cada vez que creamos nuevos modelos o modificamos los existentes
python manage.py makemigrations nombreaplicacion
Migramos cada vez que alguien de nuestro equipo ha hecho un makemigrations y hemos bajado esos cambios.
python manage.py migrate