Django: Disfruta programando.
-
Upload
jorge-bastida -
Category
Technology
-
view
11.978 -
download
1
description
Transcript of Django: Disfruta programando.
Disfruta programando.
Jorge Bas4da [neo][email protected]
Jaime Irurzun [etox] [email protected]
@jorgebas4da @jaimeirurzun
Disfruta programando.
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
• Legible
• Produc/vo
• Portable
• Extenso
• Integrable
• ... y Diver/do
Sintaxis intui4va y estricta
Entre 1/3 y 1/5 más conciso que Java o C++
GNU/Linux, Windows, Mac OS X, ...
Standard Library, Third par4es
C, C++, Java, .NET, COM, WS, CORBA, ...
Instalación
$ sudo apt-get install python
http://www.python.org/download/
Snow Leopard incluye las versiones 2.5.4 y 2.6.1
El Intérprete
El Intérprete
$ python holamundo.py hola mundo!$
Modo Batch
#!/usr/bin/env pythonprint "hola mundo!"
holamundo.py
El Intérprete
$ pythonPython 2.6.5 (r265:79063, Apr 16 2010, 13:09:56) [GCC 4.4.3] on linux2Type "help", "copyright", "credits" or "license" for more information.>>> print "hola mundo!"hola mundo!
Modo Interac4vo
$ python holamundo.py hola mundo!$
Modo Batch
#!/usr/bin/env pythonprint "hola mundo!"
holamundo.py
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
'spam' "guido's" """n lines"""str
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
'spam' "guido's" """n lines"""str
[1, [2, 'three'], 4]list
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
'spam' "guido's" """n lines"""str
[1, [2, 'three'], 4]list
{'food': 'spam', 'taste': 'yum'}dict
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
'spam' "guido's" """n lines"""str
[1, [2, 'three'], 4]list
{'food': 'spam', 'taste': 'yum'}dict
(1, 'spam', 4, 'U')tuple
Tipos de datos
+ info: h\p://docs.python.org/library/stdtypes.html
object
1234 3.1415int float35Llong
True Falsebool
'spam' "guido's" """n lines"""str
[1, [2, 'three'], 4]list
{'food': 'spam', 'taste': 'yum'}dict
(1, 'spam', 4, 'U')tuple
¡Tipado
dinámico!
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Operadores
+ info: h\p://docs.python.org/library/operator.html
Operadores
+ info: h\p://docs.python.org/library/operator.html
numéricosa + b a - b a * b a / b
a % b -a +a a ** b
Operadores
+ info: h\p://docs.python.org/library/operator.html
numéricosa + b a - b a * b a / b
a % b -a +a a ** b
comparadoresa < b a <= b a > b
a >= b a == b a != b
Operadores
+ info: h\p://docs.python.org/library/operator.html
numéricosa + b a - b a * b a / b
a % b -a +a a ** b
comparadoresa < b a <= b a > b
a >= b a == b a != b
lógicos a or b a and b not a
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Usos frecuentes: list
Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1
Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1
>>> 2 in numsTrue
Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1
>>> nums.append(4)>>> print nums[1, 2, 3, 4]
>>> 2 in numsTrue
Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1
>>> nums.append(4)>>> print nums[1, 2, 3, 4]
>>> 2 in numsTrue
>>> nums.count()4
Usos frecuentes: str
Usos frecuentes: str>>> "Python mola"[1:4]'yth'
Usos frecuentes: str>>> "Python mola"[1:4]'yth'
>>> "Python mola".find("mola")7
Usos frecuentes: str>>> "Python mola"[1:4]'yth'
>>> "Python mola".find("mola")7
>>> "Python mola".replace("Python", "PHP no")'PHP no mola'
Usos frecuentes: str>>> "Python mola"[1:4]'yth'
>>> "Python mola".find("mola")7
>>> "Python mola".replace("Python", "PHP no")'PHP no mola'
>>> "Python mola".split(" ")['Python', 'mola']
Usos frecuentes: str>>> "Python mola"[1:4]'yth'
>>> "Python mola".find("mola")7
>>> "Python mola".replace("Python", "PHP no")'PHP no mola'
>>> "Python mola".split(" ")['Python', 'mola']
>>> " ".join(["Python", "mola"])"Python mola"
Usos frecuentes: dict
Usos frecuentes: dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]
Usos frecuentes: dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]
>>> user['age']24
>>> user.get('age', 20)24
Usos frecuentes: dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]
>>> user['age']24
>>> user.get('age', 20)24
>>> user.has_key('nick')True
Usos frecuentes: dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]
>>> user['age']24
>>> user.get('age', 20)24
>>> user.has_key('nick')True
>>> user.update({'nick': 'alatar', 'age': 25})>>> user{'nick': 'alatar', 'age': 25}
Usos frecuentes: str %
Usos frecuentes: str %
>>> "%s es muy sabio" % "Hycker"'Hycker es muy sabio'
Usos frecuentes: str %
>>> "%s es muy sabio" % "Hycker"'Hycker es muy sabio'
>>> "%s sabe %i idiomas" % ("Hycker", 5)'Hycker sabe 5 idiomas'
Usos frecuentes: str %
>>> "%s es muy sabio" % "Hycker"'Hycker es muy sabio'
>>> "%s sabe %i idiomas" % ("Hycker", 5)'Hycker sabe 5 idiomas'
>>> t = "%(NOMBRE)s sabe %(IDIOMAS)i idiomas">>> v = {'NOMBRE': 'Hycker', 'IDIOMAS': 5}>>> t % v'Hycker sabe 5 idiomas'
sound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
Módulos1. Un módulo es un fichero .py
2. Los módulos pueden
organizarse en paquetes.
3. Un paquete es una carpeta
que conNene un fichero con
nombre __init__.py
sound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
Módulos1. Un módulo es un fichero .py
2. Los módulos pueden
organizarse en paquetes.
3. Un paquete es una carpeta
que conNene un fichero con
nombre __init__.py
1
2
3
Módulos
En la lista de directorios que conNene la lista sys.path:
import math ¿Dónde los busca Python?
1. El directorio actual:
2. El directorio site-packages de nuestro Python:
3. Los directorios apuntados por PYTHONPATH:
4. El directorio de la instalación de Python:
./
/usr/local/lib/python2.6/site-packages
/usr/lib/python2.6/
$ env | grep PYTHONPATH
Módulossound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
import sound.effects.echosound.effects.echo.echofilter(...)
Módulossound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
import sound.effects.echosound.effects.echo.echofilter(...)
from sound.effects import echoecho.echofilter(...)
Módulossound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
import sound.effects.echosound.effects.echo.echofilter(...)
from sound.effects import echoecho.echofilter(...)
from sound.effects.echo import echofilterechofilter(...)
Módulossound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
import sound.effects.echosound.effects.echo.echofilter(...)
from sound.effects import echoecho.echofilter(...)
from sound.effects.echo import echofilterechofilter(...)
from sound.effects.echo import *echofilter(...)
Módulossound/ __init__.py formats/ __init__.py wavread.py wavwrite.py aiffread.py aiffwrite.py auread.py auwrite.py ... effects/ __init__.py echo.py surround.py reverse.py ... filters/ __init__.py equalizer.py vocoder.py karaoke.py ...
import sound.effects.echosound.effects.echo.echofilter(...)
from sound.effects import echoecho.echofilter(...)
from sound.effects.echo import echofilterechofilter(...)
from sound.effects.echo import *echofilter(...)
from sound.effects import echo as revrev.echofilter(...)
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
{}Estructuras
{}Estructuras
>>> from __future__ import braces File "<stdin>", line 1 SyntaxError: not a chance
Identación
>>> from __future__ import braces File "<stdin>", line 1 SyntaxError: not a chance
4 Espacios para indicar la identaciónPEP 8
Identación
h\p://www.python.org/dev/peps/pep-‐0008/
• Guido van Rossum (2001)
• Recomendaciones de esNlo
• “Readability counts”
• “Code is read much more oZen than it is wri\en.”
• Muy recomendable importante seguirlo.
PEP 8¿PEP 8?
def my_first_function(p1, p2): return "Hello World!"
Funciones
def my_first_function(p1, p2): return "Hello World!"
1
Funciones
def my_first_function(p1, p2): return "Hello World!"
12
Funciones
def my_first_function(p1, p2): return "Hello World!"
12
3
Funciones
def my_first_function(p1, p2): return "Hello World!"
Recomendaciones:• Minúsculas• Palabras separadas por _• Evitar camelCase
12
3
PEP 8
Funciones
Conversión de /pos
+info: h\p://docs.python.org/library/func4ons.html
Conversión de /pos
+info: h\p://docs.python.org/library/func4ons.html
>>> int(1.3)1
Conversión de /pos
>>> str(2)'2'
+info: h\p://docs.python.org/library/func4ons.html
>>> int(1.3)1
Conversión de /pos
>>> str(2)'2'
+info: h\p://docs.python.org/library/func4ons.html
>>> int(1.3)1
>>> float(1)1.0
Conversión de /pos
>>> str(2)'2'
+info: h\p://docs.python.org/library/func4ons.html
>>> int(1.3)1
>>> float(1)1.0
>>> tuple([1,2,3])(1, 2, 3)
Conversión de /pos
>>> str(2)'2'
+info: h\p://docs.python.org/library/func4ons.html
>>> int(1.3)1
>>> float(1)1.0
>>> list((1,2,3))[1, 2, 3]
>>> tuple([1,2,3])(1, 2, 3)
Funciones comunes
+info: h\p://docs.python.org/library/func4ons.html
Funciones comunes
>>> len("Python Mola")11>>> len([1,2,3,4])4
+info: h\p://docs.python.org/library/func4ons.html
Funciones comunes
>>> len("Python Mola")11>>> len([1,2,3,4])4
>>> range(5)[0, 1, 2, 3, 4]>>> range(1,7)[1, 2, 3, 4, 5, 6]>>> range(1,7,2)[1, 3, 5]
+info: h\p://docs.python.org/library/func4ons.html
Funciones comunes
>>> len("Python Mola")11>>> len([1,2,3,4])4
>>> range(5)[0, 1, 2, 3, 4]>>> range(1,7)[1, 2, 3, 4, 5, 6]>>> range(1,7,2)[1, 3, 5]
>>> type(True)<type 'bool'>>>> type("Python Mola")<type 'str'>
+info: h\p://docs.python.org/library/func4ons.html
Funciones comunes
>>> len("Python Mola")11>>> len([1,2,3,4])4
>>> range(5)[0, 1, 2, 3, 4]>>> range(1,7)[1, 2, 3, 4, 5, 6]>>> range(1,7,2)[1, 3, 5]
>>> sum([0,1,2,3,4])10>>> sum(range(5))10
>>> type(True)<type 'bool'>>>> type("Python Mola")<type 'str'>
Y un muy largo etc...
+info: h\p://docs.python.org/library/func4ons.html
Funciones interesantes
Son sólo un ejemplo...
+info: h\p://docs.python.org/library/func4ons.html
Funciones interesantes
>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]
Son sólo un ejemplo...
+info: h\p://docs.python.org/library/func4ons.html
Funciones interesantes
>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]
>>> sorted([5,1,3,4,2])[1, 2, 3, 4, 5]
Son sólo un ejemplo...
+info: h\p://docs.python.org/library/func4ons.html
Funciones interesantes
>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]
>>> round(1.2345,2)1.23
>>> sorted([5,1,3,4,2])[1, 2, 3, 4, 5]
Son sólo un ejemplo...
+info: h\p://docs.python.org/library/func4ons.html
Funciones interesantes
>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]
>>> round(1.2345,2)1.23
>>> sorted([5,1,3,4,2])[1, 2, 3, 4, 5]
>>> map(str,[1,2,3,4,5])['1', '2', '3', '4', '5']
Son sólo un ejemplo...
+info: h\p://docs.python.org/library/func4ons.html
Funciones de ayuda
Funciones de ayuda>>> dir([1,2,3])['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
Funciones de ayuda>>> dir([1,2,3])['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
>>> help(filter)Help on built-in function filter in module __builtin__:
filter(...) filter(function or None, sequence) -> list, tuple, or string Return those items of sequence for which function(item) is true. If function is None, return the items that are true. If sequence is a tuple or string, return the same type, else return a list.(END)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1 2
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1 2
3
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1 2
3
4
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1 2
3
4
5
Clases
s = Student("Jorge", 24)
class Student(object): def __init__(self, name, age): self.name = name self.age = age def hello(self): return 'My name is %s' % self.name
1 2
3
4
5
Recomendaciones:• CamelCase
PEP 8
Clases
s = Student("Jorge", 24)
El operador ()
• Es importante diferenciar:
funcion vs funcion()
Clase vs Clase()
• El operador () permite:
• Invocar funciones:
• Instanciar clases:
resultado = funcion()
objeto = Clase("param1")
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
$name = "Jon";
if($name == "Jon"){ $name = "Jon Rocks!";}elseif($name == "Mary"){ $name = "Hello Mary";}else{ $name = "Who are you?"}
name = "Jon"
if name == "Jon": name = "Jon Rocks!"elif name == "Mary": name = "Hello Mary"else: name = "Who are you?"
Sentencias: if-‐else
$count = 0;while ($count < 5) { echo "Number ".$count; $count+=1;}
count = 0while count < 5: print "Number %i" % count count+=1
Sentencias: while
for ($i=0; $i < 5; $i++) { echo "Number ".$count;}
for i in range(4): print "Number %i" % count
Sentencias: for
try { $result = 3 / 0;} catch (Exception $e) { echo "Division by Zero"}
try: result = 3 / 0except: print "Division by Zero"
Sentencias: try-‐except
• Python es un lenguaje fácil de aprender.• Menos código:
• Muchos Muchísimos menos errores de Sintaxis.
• Mayor velocidad de escritura.
• ProtoNpado... UNlizado por grandes empresas.
Conclusiones
• Python es un lenguaje fácil de aprender.• Menos código:
• Muchos Muchísimos menos errores de Sintaxis.
• Mayor velocidad de escritura.
• ProtoNpado... UNlizado por grandes empresas.
etc...
Conclusiones
Ejemplo & Ejercicio
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Evolución de la Web
Desarrollo Web
1ª Generación 2ª Generación 3ª Generación
HTML
CGIPHP
ASP
JSP
...
Django
Rails
Symfony
...
Frameworks web
Django: Qué y dónde
• Loose coupling, Acoplamiento débil.
• Cada capa es independiente y desconoce completamente
a las demás.
• Menos código.
• Rápido desarrollo.• Esto es el siglo 21, todo el trabajo tedioso hay que evitarlo.
• Don’t Repeat Yourself (DRY)
FilosoXa
• Loose coupling, Acoplamiento débil.
• Cada capa es independiente y desconoce completamente
a las demás.
• Menos código.
• Rápido desarrollo.• Esto es el siglo 21, todo el trabajo tedioso hay que evitarlo.
• Don’t Repeat Yourself (DRY)
Every distinct concept and/or piece of data should live in one, and only one, place. Redundancy is bad. Normalization is good.”“
FilosoXa
• Explicit is be\er than implicit.
• Este es un principio de Python.• Django no debe hacer demasiada “Magia”.
• Si algo es “Mágico” ha de haber una buena razón.
• Consistencia• Ha de ser consistente a todos los niveles.
• Eficiencia, Seguridad, Flexibilidad y Simplicidad.
h\p://docs.djangoproject.com/en/dev/misc/design-‐philosophies/
FilosoXa
La comunidad
La comunidad
• django-‐users
18.000 miembros
La comunidad
• django-‐users
18.000 miembros
• django-‐developers
5.900 miembros
La comunidad
• django-‐users
18.000 miembros
• django-‐developers
5.900 miembros
• djangoproject.com
500.000 visitas únicas mensuales
¿Quién usa Django?
etc...
¿Quién usa Django?
1. Instalación Python
$ sudo apt-get install python
http://www.python.org/download/
Snow Leopard incluye las versiones 2.5.4 y 2.6.1
Configurar un motor de Base de Datos:
• Oficiales: • PostgreSQL• MySQL
• Oracle• SQLite
• Comunidad:
• Sybase SQL Anywhere• IBM DB2
• MicrosoZ SQL Server 2005
• Firebird• ODBC
2. Instalación SGBD
Configurar un motor de Base de Datos:
• Oficiales: • PostgreSQL• MySQL
• Oracle• SQLite
• Comunidad:
• Sybase SQL Anywhere• IBM DB2
• MicrosoZ SQL Server 2005
• Firebird• ODBC
2. Instalación SGBD
• Vamos a uNlizar SQLite por comodidad
• Desde Python 2.5 podemos uNlizar sqlite sin instalar nada.
2. Instalación SGBD
• Vamos a uNlizar SQLite por comodidad
• Desde Python 2.5 podemos uNlizar sqlite sin instalar nada.
2. Instalación SGBD
A: Paquetes de cada distro
• apt-get install python-django
B: Official Release
• h\p://www.djangoproject.com/download/
• python setup.py install
C: Trunk
• h\p://code.djangoproject.com/svn/django/trunk/
3. Instalación Django
All Right?
All Right?
>>> import django>>> django.VERSION(1, 1, 0, 'final', 0)
>>> import djangoTraceback (most recent call last): File "<stdin>", line 1, in <module>ImportError: No module named django
Bienvenidos al mundo de Oz
* Incluida la carpeta del proyecto
Ficheros y Carpetas¿Es Django tán simple y fácil de usar?
* Incluida la carpeta del proyecto
Ficheros y Carpetas
Ficheros
Carpetas
¿Es Django tán simple y fácil de usar?
Rails Symfony
149 117
35 29
* Incluida la carpeta del proyecto
Ficheros y Carpetas
Ficheros
Carpetas
¿Es Django tán simple y fácil de usar?
Rails Symfony
149 117
35 29
* Incluida la carpeta del proyecto
Ficheros y Carpetas
Ficheros
Carpetas
¿Es Django tán simple y fácil de usar?
Rails Symfony
149 117
35 29
* Incluida la carpeta del proyecto
Ficheros y Carpetas
Django
4
1
Ficheros
Carpetas
¿Es Django tán simple y fácil de usar?
Let’s enjoy
Crear nuestro proyectode 4 ficheros ;-‐)
Crear nuestro proyecto
$ django-admin.py startproject dwitter
de 4 ficheros ;-‐)
Crear nuestro proyecto
$ django-admin.py startproject dwitter
__init__.py
manage.py
settings.py
urls.py
de 4 ficheros ;-‐)
Crear nuestro proyecto
$ django-admin.py startproject dwitter
-‐ ¿Esto es un proyecto... ? Si os ve mi jefe...
__init__.py
manage.py
settings.py
urls.py
de 4 ficheros ;-‐)
Crear nuestro proyecto
$ django-admin.py startproject dwitter
-‐ ¿Esto es un proyecto... ? Si os ve mi jefe...
__init__.py
manage.py
settings.py
urls.py
-‐ Sí, disponemos de un proyecto ‘funcional’ en django.
de 4 ficheros ;-‐)
senngs.py
Arrancar nuestro proyectode 4 ficheros ;-‐)
Arrancar nuestro proyectode 4 ficheros ;-‐)
$ cd dwitter$ python manage.py runserver
Validating models...0 errors found
Django version 1.1, using settings 'dwitter.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.
Arrancar nuestro proyectode 4 ficheros ;-‐)
$ cd dwitter$ python manage.py runserver
Validating models...0 errors found
Django version 1.1, using settings 'dwitter.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
MVC en Django
Modelo = Model Vista = Template Controlador = URL+View
URLs y Vistas
• El fichero urls.py actúa como puerta de entrada para las pe4ciones HTTP
• Se definen URLs elegantes mediante expresiones regulares que redirigen a funciones de views.py
urls.py
views.py
h\p://mysite.com/about/
html ...
¿urlpa\erns?
URLs y Vistas
• La función de views.py recibe como parámetros un objeto
HhpRequest y todos los parámetros de la URL capturados,
teniendo que devolver siempre un objeto HhpResponse
views.py
HhpRequest(), ...
HhpResponse()
URLs y VistasEjemplo 1: http://mysite.com/time
from django.conf.urls.defaults import *from mysite.views import hora_actual
urlpatterns = patterns('', (r'^time/$', hora_actual),)
from django.http import HttpResponsefrom datetime import datetime
def hora_actual(request): now = datetime.now() html = "Son las %s." % now
return HttpResponse(html)
urls.py
views.py
URLs y Vistas
from django.conf.urls.defaults import *from mysite.views import dentro_de
urlpatterns = patterns('', (r'^time/plus/(\d{1,2})/$', dentro_de),)
from django.http import HttpResponsefrom datetime import datetime, timedelta
def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt)
return HttpResponse(html)
urls.py
views.py
Ejemplo 2: http://mysite.com/time/plus/2
URLs y Vistas
from django.conf.urls.defaults import *from mysite.views import dentro_de
urlpatterns = patterns('', (r'^time/plus/(\d{1,2})/$', dentro_de),)
from django.http import HttpResponsefrom datetime import datetime, timedelta
def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt)
return HttpResponse(html)
urls.py
views.py
Ejemplo 2: http://mysite.com/time/plus/2
¡Recuerda!: MVC
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Templates• Separan la lógica de presentación a una capa independiente.
• Ficheros independientes (.html)
• Lenguaje independiente (¡para diseñadores!)
Templates• Se basan en dos 4pos de objetos: Template() y Context().
• Un objeto Template() con4ene el string de salida que queremos devolver en el H\pResponse (normalmente HTML), pero incluyendo e4quetas especiales de Django.
• Un objeto Context() con4ene un diccionario con los valores que dan contexto a una plan4lla, los que deben usarse para renderizar un objeto Template().
"Bienvenido, {{ user }}."
{'user': 'alatar'}
Template:
Context:
"Bienvenido, alatar."
Templates
from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetime
PLANTILLA = """<html><body>Son las {{ hora }}.</body></html>"""
def hora_actual(request): now = datetime.now() t = Template(PLANTILLA) c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
• Primera aproximación al obje4vo: Template + Context
Templates• Segunda aproximación al obje4vo: open(), read(), close()
from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
Templates• Segunda aproximación al obje4vo: open(), read(), close()
from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
Templates• Segunda aproximación al obje4vo: open(), read(), close()
from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
Boring
boilerplate
code!
Templates• Tercera aproximación al obje4vo: get_template()
from django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() t = get_template('hora.html') c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.py
Templates• Tercera aproximación al obje4vo: get_template()
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.py
from django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() t = get_template('hora.html') c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
Templates• Tercera aproximación al obje4vo: get_template()
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.py
from django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetime
def hora_actual(request): now = datetime.now() t = get_template('hora.html') c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
S4ll
boring...
Templates• Obje4vo alcanzado: render_to_response()
from django.shortcuts import render_to_responsefrom datetime import datetime
def hora_actual(request): now = datetime.now() return render_to_response('hora.html', {'hora': now})
Templates• Obje4vo alcanzado: render_to_response()
from django.shortcuts import render_to_responsefrom datetime import datetime
def hora_actual(request): now = datetime.now() return render_to_response('hora.html', {'hora': now})
Boring...?
Templates• Obje4vo alcanzado: render_to_response()
from django.shortcuts import render_to_responsefrom datetime import datetime
def hora_actual(request): now = datetime.now() return render_to_response('hora.html', {'hora': now})
AWESOME!
Templates: Tip
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.pya)
Templates: Tip
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.py Reusable
apps?a)
Templates: Tip
TEMPLATE_DIRS = ( '/home/django/templates',)
sezngs.py Reusable
apps?a)
b)
• La carpeta /templates es buscada dentro de cada app.
• Conviene incluir una carpeta con el nombre de la app por claridad.
TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.load_template_source', 'django.template.loaders.app_directories.load_template_source',)
return render_to_response('website/index.html')
Alterna4va reu4lizable:
¡Empieza nuestro primer proyecto!
a) Crear la app dwi\er.website.b) Incluir la app en senngs.py.c) Definir URLs en urls.py:‣ user/<username>/status/<tweet_id>/‣ user/<username>/follow/‣ user/<username>/unfollow/‣ user/<username>/‣ search/‣ users/
d) Crear una vista para “/” que renderice un Nmeline de twi\er en una template index.html a parNr de datos hardcodeados en un diccionario.
Templates en detalle
• Si, otro sistema de templates
• Smarty, Tiles, ClearSilver ...
•Describen cuál va a ser el resultado que ven los usuarios.
• Desacoplado de Python ( Diseñadores muy lejos de Python )
• HTML (o no)... con esteroides.
• Muy sencillo de aprender
• KISS: Keep It Simple, Stupid
• Muy sencillo de extender
FilosoXa y Limitaciones
• La sintaxis debe estar desacoplada del HTML/XML.
• Los diseñadores saben HTML.
• Los diseñadores no saben Python.
• No consiste en inventarse un lenguaje.
• Una variable no puede cambiar el valor de una variable.
• Una template no puede ejecutar código Python.
Templates: {{}}
<html> <head>Ejemplo templates</head> <body> Hola, {{ username }}. </body></html>
{'username': 'juan'}
<html> <head>Ejemplo templates</head> <body> Hola, juan. </body></html>
Filters y Tags
Filters y Tags
Filters y Tags
{{ varible|filter }}filter
Filters y Tags
{{ varible|filter }}filter
{% tag var1 var2 %}inline tag
Filters y Tags
{{ varible|filter }}filter
{% tag var1 var2 %}inline tag
{% tag var1 %} ...{% endtag %}
block tag
Templates: tags {% %}
Templates: tags {% %}
{% comment %} Bu! {% endcomment %}comment
Templates: tags {% %}
{% comment %} Bu! {% endcomment %}comment
for {% for elemento in lista %} <li>{{ elemento }}<li>{% endfor %}
Templates: tags {% %}
{% comment %} Bu! {% endcomment %}comment
for {% for elemento in lista %} <li>{{ elemento }}<li>{% endfor %}
if {% if username == "Juan" %} Hola Juan, me gustas!{% else %} Hola {{ username }},{% endif %}
== != > < >= <=in and or not
Tarea 1: Tagsa) UNlizar tags para que el Nmeline se muestre con el siguiente formato:• <username>: <tweet>• <username>: <tweet>• ...
Templates: Filters
<html> <head>Ejemplo templates</head> <body> Hola, {{ username|title }}. </body></html>
{'username': 'juan'}
<html> <head>Ejemplo templates</head> <body> Hola, Juan. </body></html>
/tle
Templates: Filters
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
{{ username|cut }}cut Juanesmajo
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
{{ username|cut }}cut Juanesmajo
{{ username|slugify }}slugify juan-es-majo
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
{{ username|cut }}cut Juanesmajo
{{ username|slugify }}slugify juan-es-majo
{{ username|wordcount }}wordcount 3
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
{{ username|cut }}cut Juanesmajo
{{ username|slugify }}slugify juan-es-majo
{{ username|upper }}upper JUAN ES MAJO
{{ username|wordcount }}wordcount 3
Templates: Filters{'username': 'Juan es majo'}
{{ username|length }}length 12
{{ username|cut }}cut Juanesmajo
{{ username|slugify }}slugify juan-es-majo
{{ username|upper }}upper JUAN ES MAJO
{{ username|wordcount }}wordcount 3
{{ username|default:”Desconocido” }}default
{'username': None}
Desconocido
Templates: Filters
Templates: Filters{'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'}
{{ username|striptags }}striptags
Juan es majo guapo y listo
Templates: Filters{'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'}
{{ username|striptags }}striptags
Juan es majo guapo y listo
{{ username|truncatewords_html:4 }}truncatewords_html
Juan es <b>majo guapo</b> ...
Templates: Filters{'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'}
{{ username|striptags }}striptags
Juan es majo guapo y listo
{{ username|truncatewords_html:4 }}truncatewords_html
Juan es <b>majo guapo</b> ...
{{ username|removetags:”em a br” }}removetags
Juan es <b>majo guapo y listo</b>
Templates: Filters
Templates: Filters
{'url': 'Visitad http://www.djangoproject.com'}
{{ url|urlize }}urlize
Visitad <a href=”http://www.djangoproject.com”> http://www.djangoproject.com </a>
Templates: Filters
{'url': 'Visitad http://www.djangoproject.com'}
{{ url|urlize }}urlize
Visitad <a href=”http://www.djangoproject.com”> http://www.djangoproject.com </a>
{{ url|urlizetrunc:16 }}urlizetrunc
Visitad <a href=”http://www.djangoproject.com”> http://www.djang...</a>
Templates: Filters{'lista': ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]}
Templates: Filters{'lista': ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]}
{{ lista|unordered_list }}unordered_list
<li>States <ul> <li>Kansas <ul> <li>Lawrence</li> <li>Topeka</li> </ul> </li> <li>Illinois</li></ul></li>
Templates: Filters
Templates: Filters{'value': 123456789}
{{ value|add:”1” }}add 123456790
Templates: Filters{'value': 123456789}
{{ value|add:”1” }}add 123456790
{{ value|filesizeformat }}filesizeformat 117.7MB
Templates: Filters{'value': 123456789}
{{ value|add:”1” }}add 123456790
{{ value|filesizeformat }}filesizeformat 117.7MB
{'date': datetime.datetime(2010, 9, 11, 17, 1, 59, 385323) }
{{ date|date:”d M Y” }}date 11 Sep 2010
Templates: Filters{'value': 123456789}
{{ value|add:”1” }}add 123456790
{{ value|filesizeformat }}filesizeformat 117.7MB
{'date': datetime.datetime(2010, 9, 11, 17, 1, 59, 385323) }
{{ date|date:”d M Y” }}date 11 Sep 2010
{{ date|timesince }}/mesince 4 days, 6 hours
Templates: Filters{'value': 123456789}
{{ value|add:”1” }}add 123456790
{{ value|filesizeformat }}filesizeformat 117.7MB
{'date': datetime.datetime(2010, 9, 11, 17, 1, 59, 385323) }
{{ date|date:”d M Y” }}date 11 Sep 2010
{{ date|timesince }}/mesince 4 days, 6 hours
{{ date|timeuntil }}/meun/l 1 days, 6 hours
Tarea 2: Filtersa) Añadir a cada tweet del Nmeline el Nempo transcurrido:• <username>: <tweet>
<n> seconds ago• <username>: <tweet>
<n> minutes ago• ...
Templates: tags {% %}
Templates: tags {% %}cycle {% for elemento in lista %}
<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}
Templates: tags {% %}cycle {% for elemento in lista %}
<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}
include {% include "foo/bar.html" %}
Templates: tags {% %}cycle {% for elemento in lista %}
<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}
include {% include "foo/bar.html" %}
forloop {% for elemento in lista %} <li>{{ forloop.counter }}.{{ elemento }}<li>{% endfor %}
Templates: tags {% %}cycle {% for elemento in lista %}
<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}
include {% include "foo/bar.html" %}
forloop {% for elemento in lista %} <li>{{ forloop.counter }}.{{ elemento }}<li>{% endfor %}
empty {% for elemento in lista %} <li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% empty %} Sin elementos.{% endfor %}
Tarea 3: Tags avanzadosa) Hacer que el Nmeline muestre el mensaje “No hay tweets.” si el diccionario recibido está vacío.
extend y block
base.html <html> <head> <title>Mi página personal</title> </head> <body> {% block content %} Contenido por defecto. {% endblock %} </body></html>
hija.html {% extends "base.html" %}{% block content %} Hola desde la portada.{% endblock %}
Tarea 4: Herencia de templatesa) Descargar nuestra template base.html.b) Incluirla en vuestra app.c) Hacer que vuestro index.html herede de base.html y exNenda el bloque ‘content’ con su contenido.
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Modelos
¿SQL?
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
1
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
12
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
12
3
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
12
34
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
12
34
5
Ejemplo SQL
def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret', host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
12
34
5
6
12 lineas de Python... ¬_¬
ORM (Object-‐RelaNonal mapping)
ORM (Object-‐RelaNonal mapping)
Ejemplo ORM
def book_list(request):
names = Books.objects.all().order_by('name')
return render_to_response('book_list.html', {'names':names})
Ejemplo ORM
def book_list(request):
names = Books.objects.all().order_by('name')
return render_to_response('book_list.html', {'names':names})
1
Ejemplo ORM
def book_list(request):
names = Books.objects.all().order_by('name')
return render_to_response('book_list.html', {'names':names})
1 2
Fucking Ninjas!
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
1
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
2
1
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
2
1
3
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
2
1
3
4
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
2
1
3
4
5
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Modelofrom django.db import models
class Books(models.Model):
name = models.CharField(blank=True, max_length=100)
created = models.DateTimeField(blank=False)
available = models.BooleanField(default=True)
2
1
3
4
5
6
• Independencia SGBD!• Definimos estructuras de información genéricas.
• Definimos restricciones (notnull, blank, max_lenght...)
• Única definición del modelo (configuración, mapeo a db)
Fucking Awesome Ninjas!
Tipos de Datos
• AutoField• BigIntegerField• BooleanField• CharField• CommaSeparatedIntegerField• DateField• DateTimeField• DecimalField• EmailField• FileField• FilePathField• FloatField• ImageField• IntegerField
• IPAdressField• NullBooleanField• PositiveIntegerField• PositiveSmallIntegerField• SlugField• SmallIntegerField• TextField• TimeField• URLField• XMLField• ForeingKey• ManyToManyField• OneToOneField
Tipos de Datos
• AutoField• BigIntegerField• BooleanField• CharField• CommaSeparatedIntegerField• DateField• DateTimeField• DecimalField• EmailField• FileField• FilePathField• FloatField• ImageField• IntegerField
• IPAdressField• NullBooleanField• PositiveIntegerField• PositiveSmallIntegerField• SlugField• SmallIntegerField• TextField• TimeField• URLField• XMLField• ForeingKey• ManyToManyField• OneToOneField
Propiedades de las Field
• null (True|Flase)
• blank (True|False)
• choices (lista)
• default (valor)
• editable (True|False)
• help_text (String)
• unique (True|False)
• primary_key
• unique_for_date
• unique_for_month
• unique_for_year
Propiedades de las Field
• null (True|Flase)
• blank (True|False)
• choices (lista)
• default (valor)
• editable (True|False)
• help_text (String)
• unique (True|False)
• primary_key
• unique_for_date
• unique_for_month
• unique_for_year
¿Es magia? No.
BEGIN;CREATE TABLE "website_books" ( "id" integer NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" datetime NOT NULL, "available" bool NOT NULL);COMMIT;
BEGIN;CREATE TABLE "website_books" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" timestamp with time zone NOT NULL, "available" boolean NOT NULL);COMMIT;
¿Es magia? No.$ python manage.py sqlall website
BEGIN;CREATE TABLE "website_books" ( "id" integer NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" datetime NOT NULL, "available" bool NOT NULL);COMMIT;
BEGIN;CREATE TABLE "website_books" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" timestamp with time zone NOT NULL, "available" boolean NOT NULL);COMMIT;
¿Es magia? No.
• Nombres de tablas generados automáNcamente.
• <app_name>_lower(<model_name>)
• id como Primary Key (Personalizable)
• Las Foreing Key terminan en _id (Personalizable)
• Los Npos de datos se ajustan en función del SGBD
Configurar sesngs.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'db.sqlite'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
Configurar sesngs.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'db.sqlite'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
1
Configurar sesngs.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'db.sqlite'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
1
2
Configurar sesngs.py
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'db.sqlite'
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
1
2
3
Creando Tablas
• Crea las tablas para todos los modelos de las apps instaladas
en el fichero senngs.py
• No actualiza esquemas si la tabla existe.
• Eliminar tabla y volver a ejecutar syncdb
Creando Tablas
$ python manage.py syncdb
• Crea las tablas para todos los modelos de las apps instaladas
en el fichero senngs.py
• No actualiza esquemas si la tabla existe.
• Eliminar tabla y volver a ejecutar syncdb
Nuestro primer modelo
a)Crear modelo Tweetb)Configurar senngs.pyc) Ver el SQL generado con sqlall
syncdb$ python manage.py syncdbCreating table auth_permissionCreating table auth_groupCreating table auth_userCreating table auth_messageCreating table django_content_typeCreating table django_sessionCreating table django_siteCreating table website_tweet
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): yesUsername (Leave blank to use 'neo'): admin E-mail address: [email protected]: Password (again): Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet model
syncdb$ python manage.py syncdbCreating table auth_permissionCreating table auth_groupCreating table auth_userCreating table auth_messageCreating table django_content_typeCreating table django_sessionCreating table django_siteCreating table website_tweet
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): yesUsername (Leave blank to use 'neo'): admin E-mail address: [email protected]: Password (again): Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet model
django.contrib.auth
¿Cuantos sistemas de AutenNcación habéis programado?
¿Alguno era mejor que el anterior? ;-‐)
contrib.auth puede ser el úlNmo :D
syncdb$ python manage.py syncdbCreating table auth_permissionCreating table auth_groupCreating table auth_userCreating table auth_messageCreating table django_content_typeCreating table django_sessionCreating table django_siteCreating table website_tweet
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): yesUsername (Leave blank to use 'neo'): admin E-mail address: [email protected]: Password (again): Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet model
website.tweet
syncdb$ python manage.py syncdbCreating table auth_permissionCreating table auth_groupCreating table auth_userCreating table auth_messageCreating table django_content_typeCreating table django_sessionCreating table django_siteCreating table website_tweet
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): yesUsername (Leave blank to use 'neo'): admin E-mail address: [email protected]: Password (again): Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet model
django.contrib.auth
BD Lista para usarse
BD Lista para usarse
Nuestro primer modelo
a)Hacer syncdb
Previo: Clases del ORM
ts = Publisher.objects.all()
Model
Manager
QuerySet
Previo: __unicode__()
Previo: __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
Previo: __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
Previo: __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
Previo: __unicode__()
class Publisher(models.Model): ... def __unicode__(self): return self.name
>>> Publisher.objects.all()[<Publisher: Publisher object>]
Previo: __unicode__()
class Publisher(models.Model): ... def __unicode__(self): return self.name
>>> Publisher.objects.all()[<Publisher: Publisher object>]
>>> Publisher.objects.all()[<Publisher: Apress>]
INSERT
INSERT
>>> p = Publisher(... name='Apress',... address='2855 Telegraph Avenue',... city='Berkeley',... state_province='CA',... country='U.S.A.',... website='http://www.apress.com/')>>> p.save()
a)
o = Model(...) o.save()
INSERT
>>> p = Publisher.objects.create(... name='O'Reilly',... address='10 Fawcett St.',... city='Cambridge',... state_province='MA',... country='U.S.A.',... website='http://www.oreilly.com/')
>>> p = Publisher(... name='Apress',... address='2855 Telegraph Avenue',... city='Berkeley',... state_province='CA',... country='U.S.A.',... website='http://www.apress.com/')>>> p.save()
a)
o = Model(...) o.save()
manager.create(...)
b)
UPDATE
UPDATE
>>> ...>>> p.id52>>> p.name = 'Apress Publishing'>>> p.save()
o.save()
1
UPDATE
>>> Publisher.objects.all().update(country='USA')2
>>> ...>>> p.id52>>> p.name = 'Apress Publishing'>>> p.save()
o.save()
queryset.update(...)
1
n
DELETE
DELETE
>>> ...>>> p.id52>>> p.delete()
o.delete()
1
DELETE
>>> ps = Publisher.objects.all()>>> ps.delete()
>>> ...>>> p.id52>>> p.delete()
o.delete()
queryset.delete()
1
n
SELECT de 1 resultado
SELECT de 1 resultado
>>> Publisher.objects.get(name="Apress")<Publisher: Apress>
.get(...)
SELECT de 1 resultado
>>> Publisher.objects.get(name="Apress")<Publisher: Apress>
.get(...)
>>> Publisher.objects.get(name="Anaya")Traceback (most recent call last): ...DoesNotExist: Publisher matching query does not exist.
SELECT de 1 resultado
>>> Publisher.objects.get(name="Apress")<Publisher: Apress>
.get(...)
>>> Publisher.objects.get(country="U.S.A.")Traceback (most recent call last): ...MultipleObjectsReturned: get() returned more than one Publisher -- it returned 2! Lookup parameters were {'country': 'U.S.A.'}
>>> Publisher.objects.get(name="Anaya")Traceback (most recent call last): ...DoesNotExist: Publisher matching query does not exist.
SELECT de N resultados
SELECT de N resultados
>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: O'Reilly>]
.all()
SELECT de N resultados
>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: O'Reilly>]
.all()
>>> Publisher.objects.filter( country="U.S.A.", state_province="CA")[<Publisher: Apress>]
.filter(...)
SELECT de N resultados
>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: O'Reilly>]
.all()
>>> Publisher.objects.filter( country="U.S.A.", state_province="CA")[<Publisher: Apress>]
.filter(...)
>>> Publisher.objects.exclude( country="U.S.A.", state_province="CA")[<Publisher: O'Reilly>]
.exclude(...)
SELECT de N resultados
>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: O'Reilly>]
.all()
>>> Publisher.objects.filter( country="U.S.A.", state_province="CA")[<Publisher: Apress>]
.filter(...)
>>> Publisher.objects.exclude( country="U.S.A.", state_province="CA")[<Publisher: O'Reilly>]
.exclude(...)
¡Devuelven
QuerySets, n
o
listas!
get(), filter() y exclude()
get(), filter() y exclude()
Modelo.objects.filter(campo1="valor1", campo2="valor2")
Los parámetros pueden indicar mucho más que igualdad (=)
get(), filter() y exclude()
Modelo.objects.filter(campo1="valor1", campo2="valor2")
Los parámetros pueden indicar mucho más que igualdad (=)
campo__exact=''
campo__iexact=''
campo__contains=''
campo__icontains=''
campo__isnull=T|F
campo__day=31
campo__gt=0
campo__gte=0
campo__lt=0
campo__lte=0
campo__in=[ ,]
campo__month=12
campo__startswith=''
campo__istartswith=''
campo__endswith=''
campo__iendswith=''
campo__range=( ,)
campo__year=2010
ORDER BY
ORDER BY
>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]
.order_by(...)
ORDER BY
>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]
.order_by(...)
>>> Publisher.objects.order_by("-name")[<Publisher: O'Reilly>, <Publisher: Apress>]
ORDER BY
>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]
.order_by(...)
>>> Publisher.objects.order_by("-name")[<Publisher: O'Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by("-name", "country")[<Publisher: O'Reilly>, <Publisher: Apress>]
MúlNples campos:
ORDER BY
>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]
.order_by(...)
>>> Publisher.objects.order_by("-name")[<Publisher: O'Reilly>, <Publisher: Apress>]
>>> Publisher.objects.order_by("-name", "country")[<Publisher: O'Reilly>, <Publisher: Apress>]
MúlNples campos:
¡También
devuelve
QuerySets!
Slicing
Slicing
>>> Publisher.objects.order_by("name")[0]<Publisher: Apress>
[n:m]
>>> Publisher.objects.order_by("name")[:2][<Publisher: Apress>, <Publisher: O'Reilly>]
>>> Publisher.objects.order_by("name")[1:2][<Publisher: O'Reilly>]
Slicing
>>> Publisher.objects.order_by("name")[0]<Publisher: Apress>
[n:m]
>>> Publisher.objects.order_by("name")[:2][<Publisher: Apress>, <Publisher: O'Reilly>]
>>> Publisher.objects.order_by("name")[1:2][<Publisher: O'Reilly>]
LIMIT
Slicing
>>> Publisher.objects.order_by("name")[0]<Publisher: Apress>
[n:m]
>>> Publisher.objects.order_by("name")[:2][<Publisher: Apress>, <Publisher: O'Reilly>]
>>> Publisher.objects.order_by("name")[1:2][<Publisher: O'Reilly>]
LIMIT
OFFSET
Related Objects
Related ObjectsOneToOneField
class Coche(models.Model): motor = OneToOneField(Motor)
class Motor(models.Model): ...
1
1
Related ObjectsOneToOneField
class Coche(models.Model): motor = OneToOneField(Motor)
class Motor(models.Model): ...
>>> c.motor<Motor: Motor object>
¿Cómo usamos la relación desde las instancias?
Gracias a nosotros
1
1
Related ObjectsOneToOneField
class Coche(models.Model): motor = OneToOneField(Motor)
class Motor(models.Model): ...
>>> c.motor<Motor: Motor object>
>>> m.coche<Coche: Coche object>
¿Cómo usamos la relación desde las instancias?
Gracias a nosotros Gracias a Django
1
1
Related Objects
Related ObjectsForeignKeyField
class Blog(models.Model): ...
class Post(models.Model): blog = ForeignKeyField(Blog)
1
n
Related ObjectsForeignKeyField
class Blog(models.Model): ...
class Post(models.Model): blog = ForeignKeyField(Blog)
>>> p.blog<Blog: Blog object>
>>> b.post_set.all()[<Post: Post object>, ...]
¿Cómo usamos la relación desde las instancias?
Gracias a nosotros Gracias a Django
1
n
Related Objects
Related ObjectsManyToManyField
class Post(models.Model): tags = ManyToManyField(Tag)
class Tag(models.Model): ...
n
m
Related ObjectsManyToManyField
class Post(models.Model): tags = ManyToManyField(Tag)
class Tag(models.Model): ...
>>> p.tags.add(t1, t2)>>> p.tags.all()[<Tag: Tag object>, ...]
>>> t.post_set.add(p1, p2)>>> t.post_set.all()[<Post: Post object>, ...]
¿Cómo usamos la relación desde las instancias?
Gracias a nosotros Gracias a Django
n
m
Related Objects
Related ObjectsEn todas ellas podemos renombrar el puntero inverso
class Blog(models.Model): ...
class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts')
1
n
Related ObjectsEn todas ellas podemos renombrar el puntero inverso
class Blog(models.Model): ...
class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts')
>>> p.blog<Blog: Blog object>
>>> b.posts.all()[<Post: Post object>, ...]
Gracias a nosotros Gracias a Django
1
n
Related ObjectsEn todas ellas podemos renombrar el puntero inverso
class Blog(models.Model): ...
class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts')
>>> p.blog<Blog: Blog object>
>>> b.posts.all()[<Post: Post object>, ...]
Gracias a nosotros Gracias a Django
1
n
Cuando haya 2 relaciones entre 2 modelos, será obligatorio
Y la guinda final: ¡Todo es LAZY!
Laziness
Laziness• Las consultas sólo se ejecutarán cuando realmente se necesite obtener los objetos. En las siguientes situaciones:
• Iteraciones
• Slicing
• Serialización
• repr()
• len() !!!
• list()
• bool()
for p in Publisher.objects.all():
Publisher.objects.filter(country='USA')[0]
[Caché]
[<Publisher: Publisher object>]
len(Publisher.objects.all())
list(Publisher.objects.all())
if Publisher.objects.filter(country='USA'):
Usando el ORM
a) Insertar varios Tweets desde la shellb)Modificar views.index para que uNlice los Tweets reales de la BD
c) Implementar URL y View para ofrecer permalinks a los tweets:‣ URL: user/<username>/status/<tweet_id>
‣ View: tweet_page
‣ Template: tweet_page.html (Bajar)
d)shortcut!: get_object_or_404()
Profiles
Profile
• Problema: El modelo User de django.contrib.auth no puede
contener toda la información que necesitamos.
• Username, Password, Name.... y poco más.
• Solución: Definir un Profile (Un Modelo Agregado) para
guardar esa información.
Profilemodels.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True)
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200)
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) ...
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) ...
AUTH_PROFILE_MODULE = "website.Profile"
sesngs.py
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) ...
AUTH_PROFILE_MODULE = "website.Profile"
sesngs.py
models.py
• Cada objeto User de django.contrib.auth dispone de un método get_profile() que nos permiNrá acceder al Profile.
Profile
•Donde tengamos el User tendremos el Profile.•Donde tengamos el Profile, tendremos el User.
Profile
>>> from django.contrib.auth.models import User>>> u = User.objects.get(id=1)>>> type(u)<class 'django.contrib.auth.models.User'>
>>> profile = u.get_profile()>>> type(profile)<class 'website.models.Profile'>
•Donde tengamos el User tendremos el Profile.•Donde tengamos el Profile, tendremos el User.
1 User = 1 Profile ¿Cuándo se crea un User?
Signals
• Django incorpora un dispacher de señales para ayudar a crear aplicaciones reuNlizables.• Permite subscribirnos a “eventos” a lo largo de todo el framework y actuar frente a ellos.
• Señales interesantes:• pre_save, post_save• pre_delete, post_delete• m2m_changed• request_started, request_finished
h\p://docs.djangoproject.com/en/dev/ref/signals/
Signals
Signals
def profile_signal_callback(sender, **kwargs): if kwargs.get('created'): profile = Profile() profile.user = User.objects.get(id=kwargs.get('instance').id) profile.save()
from django.db.models.signals import post_save
post_save.connect(profile_signal_callback, sender=User, dispatch_uid="users-profilecreation-signal")
1
Signals
def profile_signal_callback(sender, **kwargs): if kwargs.get('created'): profile = Profile() profile.user = User.objects.get(id=kwargs.get('instance').id) profile.save()
from django.db.models.signals import post_save
post_save.connect(profile_signal_callback, sender=User, dispatch_uid="users-profilecreation-signal")
1
2
Signals
def profile_signal_callback(sender, **kwargs): if kwargs.get('created'): profile = Profile() profile.user = User.objects.get(id=kwargs.get('instance').id) profile.save()
from django.db.models.signals import post_save
post_save.connect(profile_signal_callback, sender=User, dispatch_uid="users-profilecreation-signal")
1
2
3
Signals
def profile_signal_callback(sender, **kwargs): if kwargs.get('created'): profile = Profile() profile.user = User.objects.get(id=kwargs.get('instance').id) profile.save()
from django.db.models.signals import post_save
post_save.connect(profile_signal_callback, sender=User, dispatch_uid="users-profilecreation-signal")
1
2
3
4
Signals
def profile_signal_callback(sender, **kwargs): if kwargs.get('created'): profile = Profile() profile.user = User.objects.get(id=kwargs.get('instance').id) profile.save()
from django.db.models.signals import post_save
post_save.connect(profile_signal_callback, sender=User, dispatch_uid="users-profilecreation-signal")
1
2
3
4
Puede estar en cualquier app de nuestro proyecto.
Se recomienda models.py
Users en dwi\er
a)Crear el modelo Profileb)Crear trigger de agregación con User mediante signals
c) Eliminar BDd)Hacer syncdb
Followers
Profilemodels.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200)
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) followers = models.ManyToManyField("self", blank=True,
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) followers = models.ManyToManyField("self", blank=True, symmetrical=False,
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) followers = models.ManyToManyField("self", blank=True, symmetrical=False, related_name="following")
models.py
Profile
class Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) followers = models.ManyToManyField("self", blank=True, symmetrical=False, related_name="following")
models.py
• m2m symmetrical (por defecto)• Si yo te sigo a N, tú me sigues a mi.
• related_name (en este caso)• Limpieza y evitar profile_set
Users en dwi\er
a)Añadir ManyToMany para los followersb)Eliminar BD c) Hacer syncdb
1,2,3 Borrar la BD.... 1,2,3... Borrar la BD
Fixtures
Fixtures• Es muy aburrido crear juegos de datos cada vez que se elimina una tabla / BD.• No nos gustan las cosas aburridas.• Ficheros (json/xml/yaml) para inicializar una Tabla.• Pueden crearse una vez dispongamos de la información:
Fixtures• Es muy aburrido crear juegos de datos cada vez que se elimina una tabla / BD.• No nos gustan las cosas aburridas.• Ficheros (json/xml/yaml) para inicializar una Tabla.• Pueden crearse una vez dispongamos de la información:
python manage.py dumpdata <appName appName appName.model ...>
Fixtures• Es muy aburrido crear juegos de datos cada vez que se elimina una tabla / BD.• No nos gustan las cosas aburridas.• Ficheros (json/xml/yaml) para inicializar una Tabla.• Pueden crearse una vez dispongamos de la información:
python manage.py dumpdata <appName appName appName.model ...>
• Se cargan uNlizando:
python manage.py loaddata <fixture fixture ...>
• Si se llaman iniAal_data y están dentro de la carpeta fixtures de la app, se cargan al ahcer el syncdb.
El poder de los fixtures
a)Crear la carpeta website/fixturesb)Descargar iniNal_data.json y meterlo en la carpeta fixtures
c) Hacer syncdbd)Implementar URL y View para ofrecer páginas de usuario:‣ URL: user/<username>/
‣ View: user_page
‣ Template: user_page.html (Bajar)
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
CRUD: Create, Retrieve, Update & Delete
django.contrib.admin
1
2
3
django.contrib.admin
1
2
3
django.contrib.admin
1
Django admin: Instalación
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:# from django.contrib import admin# admin.autodiscover()
urlpatterns = patterns('',
...
# (r'^admin/', include(admin.site.urls)),
...
)
1
2
urls.py
Django admin: Instalación
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:from django.contrib import adminadmin.autodiscover()
urlpatterns = patterns('',
...
(r'^admin/', include(admin.site.urls)),
...
)
1
2
urls.py
Django admin: Instalación
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', ...)
sezngs.py
Django admin: Instalación
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', ...)
sezngs.py
1
Actualizando la BD
Actualizando la BD
$ python manage.py syncdb
Creating table django_admin_log
Installing index for admin.LogEntry model
Admin lista para usar
¿Y nuestra app?
?
¿Y nuestra app?
admin.py• Cada app debe de tener el suyo.
• Define qué modelos serán visibles desde el admin y permite personalizar su aspecto.
from django.contrib import admin
from website.models import Tweet
class TweetAdmin(admin.ModelAdmin):
list_display = ('id','user','message','timestamp')
admin.site.register(Tweet, TweetAdmin)
Instalar Admin
a)Configurar urls.pyb)Configurar senngs.pyc) Hacer syncdbd)Comprobar que no está Tweete)Añadir admin.pyf) Probar Administración
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Formularios
Clases involucradas
Clases involucradas
Widget Componente visual equivalente a HTMLTextInput
CheckboxInput
<input type='text'...>
<input type='checkbox'...>
Clases involucradas
Widget Componente visual equivalente a HTMLTextInput
CheckboxInput
<input type='text'...>
<input type='checkbox'...>
Field Lógica de un campo, asociado a un WidgetEmailField
IPAddressFieldwidget, initial, error, ...
Clases involucradas
Widget Componente visual equivalente a HTMLTextInput
CheckboxInput
<input type='text'...>
<input type='checkbox'...>
Field Lógica de un campo, asociado a un WidgetEmailField
IPAddressFieldwidget, initial, error, ...
Form Conjunto de Fields de un formularioContactForm [nombre, email, telefono, mensaje, ...]
Fields
Fields■ BooleanField
■ CharField
■ ChoiceField
■ TypedChoiceField
■ DateField
■ DateTimeField
■ DecimalField
■ EmailField
■ FileField
■ FilePathField
■ FloatField
■ ImageField
■ IntegerField
■ IPAddressField
■ MultipleChoiceField
■ NullBooleanField
■ RegexField
■ SlugField
■ TimeField
■ URLField
■ ComboField
■ MultiValuefield
■ SplitDateTimeField
■ ModelChoiceField
■ ModelMultipleChoiceField
Fields■ BooleanField
■ CharField
■ ChoiceField
■ TypedChoiceField
■ DateField
■ DateTimeField
■ DecimalField
■ EmailField
■ FileField
■ FilePathField
■ FloatField
■ ImageField
■ IntegerField
■ IPAddressField
■ MultipleChoiceField
■ NullBooleanField
■ RegexField
■ SlugField
■ TimeField
■ URLField
■ ComboField
■ MultiValuefield
■ SplitDateTimeField
■ ModelChoiceField
■ ModelMultipleChoiceField
Creación de un Form
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100, label='Topic')
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
• Paso 1/3: Definición del formulario en forms.py
Creación de un Form
<html><body> <h1>Contact us</h1>
{% if form.errors %} <p style="color: red;"> Please correct the error{{ form.errors|pluralize }} below. </p> {% endif %}
<form action="" method="post"> <table> {{ form.as_table }} </table> <input type="submit" value="Submit"> </form></body></html>
• Paso 2/3: Maquetación del formulario en su template
Creación de un Form
from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(cd['subject'], cd['message'], ...)
# ...
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render_to_response('contact_form.html', {'form': form})
• Paso 3/3: Programación de la vista en views.py
Creación de un Form
from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(cd['subject'], cd['message'], ...)
# ...
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render_to_response('contact_form.html', {'form': form})
• Paso 3/3: Programación de la vista en views.py
Pa\ern
Creación de un Form
from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(cd['subject'], cd['message'], ...)
# ...
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render_to_response('contact_form.html', {'form': form})
• Paso 3/3: Programación de la vista en views.py
Pa\ern
Creación de un Form
from django.shortcuts import render_to_response
from mysite.contact.forms import ContactForm
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
send_mail(cd['subject'], cd['message'], ...)
# ...
return HttpResponseRedirect('/contact/thanks/')
else:
form = ContactForm()
return render_to_response('contact_form.html', {'form': form})
• Paso 3/3: Programación de la vista en views.py
Pa\ern
Validación propia
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message
Podemos programar validación extra asociada a cada Field del formulario escribiendo un método clean_<fieldname>:
Validación propia
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
email = forms.EmailField(required=False)
message = forms.CharField(widget=forms.Textarea)
def clean_message(self):
message = self.cleaned_data['message']
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message
Podemos programar validación extra asociada a cada Field del formulario escribiendo un método clean_<fieldname>:
Maquetación propia
...<form action="" method="post"> <div class="field"> {{ form.subject.errors }} <label for="id_subject">Subject:</label> {{ form.subject }} </div> <div class="field"> {{ form.email.errors }} <label for="id_email">E-mail:</label> {{ form.email }} </div> ... <input type="submit" value="Submit"></form>...
Podemos personalizar la maquetación tanto como queramos, prescindiendo de las ayudas de form.as_table:
<style type="text/css"> ul.errorlist { ... } .errorlist li { ... }
</style>
Para los diseñadores:
Forms a parNr de Models: El COLMO del DRY
Forms a par/r de Modelsfrom django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField(blank=True, null=True)
country = models.ModelChoiceField(Country)
...
from django import forms
from books.models import Author
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
exclude = ('country',)
models.py
forms.py
Primer Form en dwi\er
a)Crear un Form que permita publicar tweets desde index.html al usuario que esté logueado desde django.contrib.admin (no tenemos login propio).
Índice
1.Python
a. Introducción
b.Tipos de datos
c. Operadores
d.Usos frecuentes
e. Estructuras
f. Sentencias
g. Ejercicio
2.Django
a. Introducción
b.URLs y Vistas
c. Templates
d.Modelo
e. Administración
f. Formularios
g. Magia avanzada
Proyecto
Magia avanzada
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
Context ProcessorsProblema
!
! ! !
!
!
!
!
Context ProcessorsSolución: el objeto RequestContext()
c = RequestContext(request, {'tweets': tweets})
• Sus4tuye a Context().
• Recibe un H\pRequest() antes del diccionario.
• Automá4camente alimenta nuestro diccionario con todos
los diccionarios devueltos por los Context Processors que
tengamos habilitados.
Context Processors¿Context Processors? Son funciones.
• Reciben un H\pRequest() como único parámetro.
• Devuelven un diccionario para ser usado como Context().
Context Processors¿Context Processors? Son funciones.
def ip_address_processor(request): return {'ip_address': request.META['REMOTE_ADDR']}
• Reciben un H\pRequest() como único parámetro.
• Devuelven un diccionario para ser usado como Context().
Context Processors¿Context Processors? Son funciones.
def ip_address_processor(request): return {'ip_address': request.META['REMOTE_ADDR']}
• Reciben un H\pRequest() como único parámetro.
• Devuelven un diccionario para ser usado como Context().
TEMPLATE_CONTEXT_PROCESSORS = ( "django.contrib.auth.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", "django.contrib.messages.context_processors.messages", "website.context_processors.ip_address_processor",)
Context Processors¿Qué ocurre con render_to_response()?
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Context Processors¿Qué ocurre con render_to_response()?
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
Context Processors¿Qué ocurre con render_to_response()?
def some_view(request):
# ...
return render_to_response('my_template.html',
my_data_dictionary,
context_instance=RequestContext(request))
from django.shortcuts import render_to_responsefrom django.template import RequestContext
def render_response(req, *args, **kwargs): kwargs['context_instance'] = RequestContext(req) return render_to_response(*args, **kwargs)
Consejo
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
MiddlewareNos permite escribir funcionalidad reu4lizable que se inserta en el flujo de ejecución de Django
Middlewareclass MyMiddleware(object):
def process_request(self, request): """Se ejecuta antes de que Django decida a qué View llamar. -> HttpRequest(): Se corta el flujo de middleware. -> None: El flujo sigue con el siguiente middleware.""" # ... def process_view(self, request, view_func, view_args, view_kwargs): """Se ejecuta antes de que se llame a la View. -> HttpRequest(): Se corta el flujo de middleware. -> None: El flujo sigue con el siguiente middleware.""" # ...
def process_response(self, request, response): """Se ejecuta después de que la View devuelva una response. -> HttpResponse()""" # ...
def process_exception(self, request, exception): """Se ejecuta cuando una View lanza una excepción. -> HttpResponse(). -> None: La excepción se propaga hasta el cliente.""" # ...
MiddlewareTenemos que incluir nuestro middleware en el lugar que nos convenga, teniendo en cuenta el orden de
ejecución en la Request y en la Response:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
caching
•Si queremos escalar nuestro proyecto rápidamente.... Cache!
•Recomendado = memcached
•Acceder a la BD es caro, muy caro.
•El Hardware es “gra4s” en comparación con op4mizar código op4mizado.
•Ejemplo (Facebook):
caching
•Si queremos escalar nuestro proyecto rápidamente.... Cache!
•Recomendado = memcached
•Acceder a la BD es caro, muy caro.
•El Hardware es “gra4s” en comparación con op4mizar código op4mizado.
•Ejemplo (Facebook):
300+Tb Memcached
caching
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)def my_view(request): ...
views
caching
from django.views.decorators.cache import cache_page
@cache_page(60 * 15)def my_view(request): ...
views
{% load cache %}{% cache 500 sidebar %} .. sidebar ..{% endcache %}
templates
caching
low level
caching
low level
>>> from django.core.cache import cache>>> cache.set('my_key', 'hello, world!', 30)>>> cache.get('my_key')'hello, world!'
•Podemos cachear cualquier 4po de objeto que se pueda serializar.
• QuerySets• Listas• ...
memcached DEMO
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
Deploying Django
Deploying Django
Virtualenv + PIP + Fabric
Virtualenv
•Independencia completa de las librerías del sitema.
•Cada proyecto 4ene su juego de librerías en la versión que necesita•Sin miedo a actualizar
•Sin miedo a migrar
•etc...
Virtualenv
•Independencia completa de las librerías del sitema.
•Cada proyecto 4ene su juego de librerías en la versión que necesita•Sin miedo a actualizar
•Sin miedo a migrar
•etc...
$ virtualenv --no-site-packages mi_entorno
crear
Virtualenv
•Independencia completa de las librerías del sitema.
•Cada proyecto 4ene su juego de librerías en la versión que necesita•Sin miedo a actualizar
•Sin miedo a migrar
•etc...
$ virtualenv --no-site-packages mi_entorno
crear
$ source mi_entorno/bin/activate
ac/var
PIP
•Gestor de paquetes del siglo 21 :D•Permite especificar un fichero de REQUIREMENTS con un listado de paquetes a instalar.
PIP
•Gestor de paquetes del siglo 21 :D•Permite especificar un fichero de REQUIREMENTS con un listado de paquetes a instalar.
Django==1.2.1psycopg2feedparser==4.1stripogram==1.5GChartWrapper==0.8
pip install -E mi_entorno -r REQUIREMENTS
Fabric
Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored“
Fabric
env.user = "example"env.hosts = ["example.com"]def deploy(): run('svn up /home/example/') sudo('/etc/init.d/lighttpd restart')
fabfile.py
Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored“
Fabric
env.user = "example"env.hosts = ["example.com"]def deploy(): run('svn up /home/example/') sudo('/etc/init.d/lighttpd restart')
fabfile.py
fabric deploy
uso
Repetition leads to boredom, boredom to horrifying mistakes, horrifying mistakes to God-I-wish-I-was-still-bored“
Magia avanzada
1. Context Processors
2.Middleware
3. Caching
4. Deploying Django
5. Apps recomendadas
Apps
django-‐registra/on
h\p://bitbucket.org/ubernostrum/django-‐registra4on/
django-‐registra/on
h\p://bitbucket.org/ubernostrum/django-‐registra4on/
•Sistema completo para la ges4ón de usuarios.
•Desde el registro, ac4vación etc...
•DRY!!
•Instalación muy sencilla.
•Recomedado ++
django-‐registra/on
h\p://bitbucket.org/ubernostrum/django-‐registra4on/
django-‐registra/on
h\p://bitbucket.org/ubernostrum/django-‐registra4on/
/ac4vate/complete//ac4vate/<ac4va4on_key>// register// register/complete// register/closed// login// logout// password/change// password/change/done// password/reset// password/reset/confirm/<token>/ password/reset/complete// password/reset/done// reac4vate/
django-‐socialregistra/on
h\p://github.com/flashingpumpkin/django-‐socialregistra4on
django-‐socialregistra/on
h\p://github.com/flashingpumpkin/django-‐socialregistra4on
•Configuración sencilla
•Auten4cación con:
•twi\er, facebook, oauth, openid
•Integración perfecta con contrib.auth
dajaxproject
h\p://dajaxproject.com
dajaxproject
h\p://dajaxproject.com
•Comunicación AJAX muy sencilla
•CrossBrowsing
•Muy ú4l si no sabemos demasiado JS
django-‐locale-‐url
h\p://code.google.com/p/django-‐localeurl/
django-‐locale-‐url
h\p://code.google.com/p/django-‐localeurl/
• Nos permite especificar el idioma en la url
www.example.com/en/
www.example.com/es/
• Mejoras en el SEO
• Cada página 4ene una única url.
• Configuración no tan sencilla, pero interesante.
django-‐piston
h\p://bitbucket.org/jespern/django-‐piston/wiki/Home
django-‐piston
h\p://bitbucket.org/jespern/django-‐piston/wiki/Home
• Framework para crear APIs RESTful
• Muy fácil instalación
• Serialización a:
•JSON, YAML, Python Pyckle, XML ...
•OAuth
•Recomendado +++++
django-‐sentry
h\p://github.com/dcramer/django-‐sentry
django-‐sentry
h\p://github.com/dcramer/django-‐sentry
django-‐debug-‐toolbar
h\p://github.com/robhudson/django-‐debug-‐toolbar
django-‐command-‐extensions
h\p://code.google.com/p/django-‐command-‐extensions/
django-‐command-‐extensions
h\p://code.google.com/p/django-‐command-‐extensions/
•Extensión para “manage.py”
•Muchas u4lidades para el día a día
•Una de las mejores: graph_models
•Usando GraphViz genera un modelo relacional de los modelos de
nuestro proyecto.
django-‐command-‐extensions
django-‐command-‐extensions
django-‐command-‐extensions
django-‐command-‐extensions
Textmate + Django
h\ps://bitbucket.org/bkerr/django-‐textmate-‐bundles
Textmate + Django
h\ps://bitbucket.org/bkerr/django-‐textmate-‐bundles
•Shortcuts para crear:•Modelos
•Fields•Filters•TemplateTags
•Forms
•Admin
Durante el curso lo hemos u4lizado.
La punta del iceberg
Disfruta programando.
Jorge Bas4da [neo][email protected]
Jaime Irurzun [etox] [email protected]
@jorgebas4da @jaimeirurzun