+ All Categories

Django

Date post: 20-Dec-2014
Category:
Upload: betabeers
View: 694 times
Download: 0 times
Share this document with a friend
Description:
 
347
Juan Riaza @juanriaza
Transcript
Page 1: Django

Juan Riaza

@juanriaza

Page 2: Django

Don’t reinvent the wheel

Page 5: Django
Page 6: Django

• Legible

• Produc-vo

• Portable

• Extenso

• Integrable

• ...  y  Diver-do

Sintaxis  intui+va  y  estricta

Entre  1/3  y  1/5  más  conciso  que  Java  o  C++

GNU/Linux,  Windows,  Mac  OS  X,  ...

Standard  Library,  Third  par+es

C,  C++,  Java,  .NET,  COM,  WS,  CORBA,  ...

Page 7: Django

El  Intérprete

Page 8: Django

El  Intérprete

$ python holamundo.py hola mundo!$

Modo  Batch

#!/usr/bin/env pythonprint "hola mundo!"

holamundo.py

Page 9: Django

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  Interac0vo

$ python holamundo.py hola mundo!$

Modo  Batch

#!/usr/bin/env pythonprint "hola mundo!"

holamundo.py

Page 10: Django

Tipos  de  datos

 h>p://docs.python.org/library/stdtypes.html

object

Page 11: Django

Tipos  de  datos

 h>p://docs.python.org/library/stdtypes.html

object

1234 3.1415int float35Llong

Page 12: Django

Tipos  de  datos

 h>p://docs.python.org/library/stdtypes.html

object

1234 3.1415int float35Llong

True Falsebool

Page 13: Django

Tipos  de  datos

 h>p://docs.python.org/library/stdtypes.html

object

1234 3.1415int float35Llong

True Falsebool

'spam' "guido's" """n lines"""str

Page 14: Django

Tipos  de  datos

 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

Page 15: Django

Tipos  de  datos

 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

Page 16: Django

Tipos  de  datos

 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

Page 17: Django

Tipos  de  datos

 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!

Page 18: Django

Operadores

 h>p://docs.python.org/library/operator.html

Page 19: Django

Operadores

numéricosa + b a - b a * b a / b

a % b -a +a a ** b

 h>p://docs.python.org/library/operator.html

Page 20: Django

Operadores

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

 h>p://docs.python.org/library/operator.html

Page 21: Django

Operadores

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

 h>p://docs.python.org/library/operator.html

Page 22: Django

Usos  frecuentes:  list

Page 23: Django

Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1

Page 24: Django

Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1

>>> 2 in numsTrue

Page 25: Django

Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1

>>> nums.append(4)>>> print nums[1, 2, 3, 4]

>>> 2 in numsTrue

Page 26: Django

Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1

>>> nums.append(4)>>> print nums[1, 2, 3, 4]

>>> 2 in numsTrue

>>> len(nums)4

Page 27: Django

Usos  frecuentes:  str

Page 28: Django

Usos  frecuentes:  str>>> "Python mola"[1:4]'yth'

Page 29: Django

Usos  frecuentes:  str>>> "Python mola"[1:4]'yth'

>>> "Python mola".find("mola")7

Page 30: Django

Usos  frecuentes:  str>>> "Python mola"[1:4]'yth'

>>> "Python mola".find("mola")7

>>> "Python mola".replace("Python", "PHP no")'PHP no mola'

Page 31: Django

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']

Page 32: Django

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"

Page 33: Django

Usos  frecuentes:  dict

Page 34: Django

Usos  frecuentes:  dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]

Page 35: Django

Usos  frecuentes:  dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]

>>> user['age']24

>>> user.get('age', 20)24

Page 36: Django

Usos  frecuentes:  dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]

>>> user['age']24

>>> user.get('age', 20)24

>>> 'nick' in userTrue

Page 37: Django

Usos  frecuentes:  dict>>> user = {'nick': 'neo', 'age': 24}>>> user.keys()['nick', 'age']>>> user.values()['neo', 24]

>>> user['age']24

>>> user.get('age', 20)24

>>> 'nick' in userTrue

>>> user.update({'nick': 'alatar', 'age': 25})>>> user{'nick': 'alatar', 'age': 25}

Page 38: Django

Usos  frecuentes:  str  %

Page 39: Django

Usos  frecuentes:  str  %

>>> "%s es muy sabio" % "Hycker"'Hycker es muy sabio'

Page 40: Django

Usos  frecuentes:  str  %

>>> "%s es muy sabio" % "Hycker"'Hycker es muy sabio'

>>> "%s sabe %i idiomas" % ("Hycker", 5)'Hycker sabe 5 idiomas'

Page 41: Django

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'

Page 42: Django

juego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.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  con+ene  un  fichero  con  

nombre  __init__.py

Page 43: Django

juego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.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  con+ene  un  fichero  con  

nombre  __init__.py

1

23

Page 44: Django

Módulosjuego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.py ...

Page 45: Django

Módulosjuego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.py ...

>>> from juego.personajes.mario import Mario>>> Mario()

>>> from juego.personajes.mario import *>>> Mario()

>>> from juego import personajes>>> personajes.mario.Mario()

Page 46: Django

{}Estructuras

Page 47: Django

{}Estructuras

Page 48: Django

>>> from __future__ import braces File "<stdin>", line 1 SyntaxError: not a chance

Identación

4  Espacios  para  la  identación

Page 49: Django

>>> from __future__ import braces File "<stdin>", line 1 SyntaxError: not a chance

Identación

4  Espacios  para  la  identaciónPEP 8

Page 50: Django

•  Guido  van  Rossum  (2001)

•  Recomendaciones  de  es0lo

•  “Readability  counts”

•  “Code  is  read  much  more  oQen  than  it  is  wriSen.”

•  Muy  recomendable  importante  seguirlo.

PEP 8¿PEP  8?

 h>p://www.python.org/dev/peps/pep-­‐0008/

Page 53: Django

Conversión  de  -pos

 h>p://docs.python.org/library/func-ons.html

Page 54: Django

Conversión  de  -pos

>>> int(1.3)1

 h>p://docs.python.org/library/func-ons.html

Page 55: Django

Conversión  de  -pos

>>> str(2)'2'

>>> int(1.3)1

 h>p://docs.python.org/library/func-ons.html

Page 56: Django

Conversión  de  -pos

>>> str(2)'2'

>>> int(1.3)1

>>> float(1)1.0

 h>p://docs.python.org/library/func-ons.html

Page 57: Django

Conversión  de  -pos

>>> str(2)'2'

>>> int(1.3)1

>>> float(1)1.0

>>> tuple([1,2,3])(1, 2, 3)

 h>p://docs.python.org/library/func-ons.html

Page 58: Django

Conversión  de  -pos

>>> str(2)'2'

>>> int(1.3)1

>>> float(1)1.0

>>> list((1,2,3))[1, 2, 3]

>>> tuple([1,2,3])(1, 2, 3)

 h>p://docs.python.org/library/func-ons.html

Page 59: Django

Funciones  comunes

 h>p://docs.python.org/library/func-ons.html

Page 60: Django

Funciones  comunes

>>> len("Python Mola")11>>> len([1,2,3,4])4

 h>p://docs.python.org/library/func-ons.html

Page 61: Django

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]

 h>p://docs.python.org/library/func-ons.html

Page 62: Django

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'>

 h>p://docs.python.org/library/func-ons.html

Page 63: Django

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...

 h>p://docs.python.org/library/func-ons.html

Page 64: Django

Funciones  interesantes

Son  sólo  un  ejemplo...

 h>p://docs.python.org/library/func-ons.html

Page 65: Django

Funciones  interesantes

>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]

Son  sólo  un  ejemplo...

 h>p://docs.python.org/library/func-ons.html

Page 66: Django

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...

 h>p://docs.python.org/library/func-ons.html

Page 67: Django

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...

 h>p://docs.python.org/library/func-ons.html

Page 68: Django

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...

 h>p://docs.python.org/library/func-ons.html

Page 69: Django

Funciones  de  ayuda

Page 70: Django

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']

Page 71: Django

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)

Page 72: Django

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)

camelCase

Page 73: Django

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)

camelCasePEP 8

Page 74: Django

El  operador  ()

• Es  importante  diferenciar:

funcion      vs      funcion()

Clase              vs        Clase()

• El  operador  ()  permite:

• Invocar  funciones:

• Instanciar  clases:

resultado = funcion()

objeto = Clase("param1")

Page 75: Django

$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

Page 76: Django

$count = 0;while ($count < 5) { echo "Number ".$count; $count+=1;}

count = 0while count < 5: print "Number %i" % count count+=1

Sentencias:  while

Page 77: Django

for ($i=0; $i < 5; $i++) { echo "Number ".$count;}

for i in range(4): print "Number %i" % count

Sentencias:  for

Page 78: Django

try { $result = 3 / 0;} catch (Exception $e) { echo "Division by Zero"}

try: result = 3 / 0except: print "Division by Zero"

Sentencias:  try-­‐except

Page 79: Django

•  Python  es  un  lenguaje  fácil  de  aprender.•  Menos  código:

•  Muchos  Muchísimos  menos  errores  de  Sintaxis.

•  Mayor  velocidad  de  escritura.

•  Proto0pado...  U0lizado  por  grandes  empresas.

Conclusiones

Page 80: Django

•  Python  es  un  lenguaje  fácil  de  aprender.•  Menos  código:

•  Muchos  Muchísimos  menos  errores  de  Sintaxis.

•  Mayor  velocidad  de  escritura.

•  Proto0pado...  U0lizado  por  grandes  empresas.

etc...

Conclusiones

Page 81: Django
Page 82: Django

Evolución  de  la  Web

Desarrollo  Web

1ª  Generación 2ª  Generación 3ª  Generación

HTML

CGIPHP

ASP

JSP

...

Django

Rails

Symfony

...

Page 83: Django

Frameworks  web

Page 84: Django

Django:  Qué  y  dónde

Page 85: Django

•  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)

Filoso\a

Page 86: Django

•  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.”“

Filoso\a

Page 87: Django

•  Explicit  is  beSer  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.

Filoso\a

 h>p://docs.djangoproject.com/en/dev/misc/design-­‐philosophies/

Page 88: Django

La  comunidad

Page 89: Django

La  comunidad

• django-­‐users

22.000  miembros

• django-­‐developers

7.000  miembros

• djangoproject.com

+500.000  visitas  únicas  mensuales

Page 90: Django

¿Quién  usa  Django?

Page 91: Django

¿Quién  usa  Django?

Page 92: Django
Page 93: Django

Bienvenidos  al  mundo  de  Oz

Page 94: Django

*  Incluida  la  carpeta  del  proyecto

Ficheros  y  Carpetas¿Es  Django  tán  simple  y  fácil  de  usar?

Page 95: Django

*  Incluida  la  carpeta  del  proyecto

Ficheros  y  Carpetas

Ficheros

Carpetas

¿Es  Django  tán  simple  y  fácil  de  usar?

Page 96: Django

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?

Page 97: Django

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?

Page 98: Django

Rails Symfony

149 117

35 29

*  Incluida  la  carpeta  del  proyecto

Ficheros  y  Carpetas

Django

5

2

Ficheros

Carpetas

¿Es  Django  tán  simple  y  fácil  de  usar?

Page 99: Django

Let’s  enjoy

Page 100: Django

Crear  nuestro  proyectode  5  ficheros  ;-­‐)

Page 101: Django

Crear  nuestro  proyecto

$ django-admin startproject dwitter

de  5  ficheros  ;-­‐)

Page 102: Django

Crear  nuestro  proyecto

$ django-admin startproject dwitter

-­‐  ¿Esto  es  un  proyecto...  ?      Si  os  ve  mi  jefe...

.!"" dwitter#   !"" __init__.py#   !"" settings.py#   !"" urls.py#   $"" wsgi.py$"" manage.py

-­‐  Sí,  disponemos  de  un  proyecto  ‘funcional’  en  django.

de  5  ficheros  ;-­‐)

Page 103: Django

seungs.py

Page 104: Django

Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)

Page 105: Django

Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)

$ cd dwitter$ python manage.py runserver

Validating models...0 errors found

Django version 1.4, using settings 'dwitter.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.

Page 106: Django

Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)

$ cd dwitter$ python manage.py runserver

Validating models...0 errors found

Django version 1.4, using settings 'dwitter.settings'Development server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.

Page 107: Django

MVC  en  Django

Modelo  =  Model Vista  =  Template Controlador  =  URL+View

Page 108: Django

URLs  y  Vistas

• El  fichero  urls.py  actúa  como  puerta  de  entrada  para  las  pe0ciones  HTTP

• Se  definen  URLs  elegantes  mediante  expresiones  regulares  que  redirigen  a  funciones  de  views.py

urls.py

views.py

hSp://mysite.com/about/

html ...

¿urlpaSerns?

Page 109: Django

URLs  y  Vistas

• La  función  de  views.py  recibe  como  parámetros  un  objeto  

H>pRequest  y  todos  los  parámetros  de  la  URL  capturados,  

teniendo  que  devolver  siempre  un  objeto  H>pResponse

views.py

H>pRequest(),  ...

H>pResponse()

Page 110: Django

URLs  y  VistasEjemplo  1:    http://mysite.com/time

from django.conf.urls.defaults import *from mysite.views import hora_actual

urlpatterns = patterns('', url(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

Page 111: Django

URLs  y  Vistas

from django.conf.urls.defaults import *from mysite.views import dentro_de

urlpatterns = patterns('', url(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

Page 112: Django
Page 113: Django

URLs  y  Vistas

from django.conf.urls.defaults import *from mysite.views import dentro_de

urlpatterns = patterns('', url(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

Page 114: Django

¡Recuerda!:  MVC

Page 115: Django

Templates• Separan  la  lógica  de  presentación  a  una  capa  independiente.

• Ficheros  independientes  (.html)

• Lenguaje  independiente  (¡para  diseñadores!)

Page 116: Django

Templates• Se  basan  en  dos  0pos  de  objetos:  Template()  y  Context().

• Un  objeto  Template()  con0ene  el  string  de  salida  que  queremos  devolver  en  el  HSpResponse  (normalmente  HTML),  pero  incluyendo  e0quetas  especiales  de  Django.

• Un  objeto  Context()  con0ene  un  diccionario  con  los  valores  que  dan  contexto  a  una  plan0lla,  los  que  deben  usarse  para  renderizar  un  objeto  Template().

"Bienvenido, {{ user }}."

{'user': 'alatar'}

Template:

Context:

"Bienvenido, alatar."

Page 117: Django

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  obje0vo:  Template  +  Context

Page 118: Django

Templates• Segunda  aproximación  al  obje0vo:  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)

Page 119: Django

Templates• Segunda  aproximación  al  obje0vo:  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)

Page 120: Django

Templates• Segunda  aproximación  al  obje0vo:  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!

Page 121: Django

Templates• Tercera  aproximación  al  obje0vo:  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',)

seungs.py

Page 122: Django

Templates• Tercera  aproximación  al  obje0vo:  get_template()

TEMPLATE_DIRS = ( '/home/django/templates',)

seungs.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)

Page 123: Django

Templates• Tercera  aproximación  al  obje0vo:  get_template()

TEMPLATE_DIRS = ( '/home/django/templates',)

seungs.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)

S0ll  

boring...

Page 124: Django

Templates• Obje0vo  alcanzado:  render()

from django.shortcuts import renderfrom datetime import datetime

def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now})

Page 125: Django

Templates• Obje0vo  alcanzado:  render()

from django.shortcuts import renderfrom datetime import datetime

def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now})

Boring...?

Page 126: Django

Templates• Obje0vo  alcanzado:  render()

from django.shortcuts import renderfrom datetime import datetime

def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now})

AWESOME!

Page 127: Django

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

Page 128: Django

Filoso\a  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.

Page 129: Django

Templates:  {{}}

<html> <head>Ejemplo templates</head> <body> Hola, {{ username }}. </body></html>

{'username': 'juan'}

<html> <head>Ejemplo templates</head> <body> Hola, juan. </body></html>

Page 130: Django

Filters  y  Tags

Page 131: Django

Filters  y  Tags

Page 132: Django

Filters  y  Tags

{{ varible|filter }}filter

Page 133: Django

Filters  y  Tags

{{ varible|filter }}filter

{% tag var1 var2 %}inline  tag

Page 134: Django

Filters  y  Tags

{{ varible|filter }}filter

{% tag var1 var2 %}inline  tag

{% tag var1 %} ...{% endtag %}

block  tag

Page 135: Django

Templates:  tags  {%  %}

Page 136: Django

Templates:  tags  {%  %}

{% comment %} Bu! {% endcomment %}comment

Page 137: Django

Templates:  tags  {%  %}

{% comment %} Bu! {% endcomment %}comment

for {% for elemento in lista %} <li>{{ elemento }}<li>{% endfor %}

Page 138: Django

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

Page 139: Django

Templates:  tags  {%  %}

Page 140: Django

Templates:  tags  {%  %}cycle {% for elemento in lista %}

<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}

Page 141: Django

Templates:  tags  {%  %}cycle {% for elemento in lista %}

<li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li>{% endfor %}

include {% include "foo/bar.html" %}

Page 142: Django

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 %}

Page 143: Django

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 %}

Page 144: Django

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

Page 145: Django

Templates:  Filters

Page 146: Django

Templates:  Filters{'username': 'Juan es majo'}

{{ username|length }}length 12

Page 147: Django

Templates:  Filters{'username': 'Juan es majo'}

{{ username|length }}length 12

{{ username|cut }}cut Juanesmajo

Page 148: Django

Templates:  Filters{'username': 'Juan es majo'}

{{ username|length }}length 12

{{ username|cut }}cut Juanesmajo

{{ username|slugify }}slugify juan-es-majo

Page 149: Django

Templates:  Filters{'username': 'Juan es majo'}

{{ username|length }}length 12

{{ username|cut }}cut Juanesmajo

{{ username|slugify }}slugify juan-es-majo

{{ username|wordcount }}wordcount 3

Page 150: Django

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

Page 151: Django

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

Page 152: Django

Templates:  Filters

Page 153: Django

Templates:  Filters{'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'}

{{ username|striptags }}striptags

Juan es majo guapo y listo

Page 154: Django

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> ...

Page 155: Django

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>

Page 156: Django

Templates:  Filters

Page 157: Django

Templates:  Filters{'value': 123456789}

{{ value|add:”1” }}add 123456790

Page 158: Django

Templates:  Filters{'value': 123456789}

{{ value|add:”1” }}add 123456790

{{ value|filesizeformat }}filesizeformat 117.7MB

Page 159: Django

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

Page 160: Django

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

Page 161: Django

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

Page 162: Django

Herencia  de  Templates

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 %}

Page 163: Django

Modelos

Page 164: Django

¿SQL?

Page 165: Django

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})

Page 166: Django

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

Page 167: Django

12  lineas  de  Python...  ¬_¬

Page 168: Django

ORM  (Object-­‐Rela0onal  mapping)

Page 169: Django

Ejemplo  ORM

def book_list(request):

names = Books.objects.all().order_by('name')

return render(request, 'book_list.html', {'names':names})

Page 170: Django

Ejemplo  ORM

def book_list(request):

names = Books.objects.all().order_by('name')

return render(request, 'book_list.html', {'names':names})

1 2

Page 171: Django

Fucking  Ninjas!

Page 172: Django

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)  

Page 173: Django

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)  

Page 174: Django

Fucking  Awesome  Ninjas!

Page 175: Django

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

Page 176: Django

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

Page 177: Django

¿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;

Page 178: Django

¿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;

Page 179: Django

Configurar  sesngs.py

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.',

'NAME': '',

'USER': '',

'PASSWORD': '',

'HOST': '',

'PORT': '',

}

}

'postgresql_psycopg2',

'postgresql', 'mysql',

'sqlite3' or 'oracle'.

Page 180: Django

Configurar  sesngs.py

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.',

'NAME': '',

'USER': '',

'PASSWORD': '',

'HOST': '',

'PORT': '',

}

}

1

2

3

'postgresql_psycopg2',

'postgresql', 'mysql',

'sqlite3' or 'oracle'.

Page 181: Django

Creando  Tablas

•  Crea  las  tablas  para  todos  los  modelos  de  las  apps  instaladas  

en  el  fichero  seungs.py

•  No  actualiza  esquemas  si  la  tabla  existe.

•  Eliminar  tabla  y  volver  a  ejecutar  syncdb

Page 182: Django

Creando  Tablas

$ python manage.py syncdb

•  Crea  las  tablas  para  todos  los  modelos  de  las  apps  instaladas  

en  el  fichero  seungs.py

•  No  actualiza  esquemas  si  la  tabla  existe.

•  Eliminar  tabla  y  volver  a  ejecutar  syncdb

Page 183: Django

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

Page 184: Django

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

Page 185: Django

¿Cuantos  sistemas  de  Auten0cación  habéis  programado?

Page 186: Django

¿Alguno  era  mejor  que  el  anterior?  ;-­‐)

Page 187: Django

contrib.auth  puede  ser  el  úl0mo  :D

Page 188: Django

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

Page 189: Django

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

Page 190: Django

BD  Lista  para  usarse

Page 191: Django

BD  Lista  para  usarse

Page 192: Django
Page 193: Django

Previo:  Clases  del  ORM

ts = Publisher.objects.all()

Model

Manager

QuerySet

Page 194: Django

INSERT

Page 195: Django

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()

Page 196: Django

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)

Page 197: Django

UPDATE

Page 198: Django

UPDATE

>>> ...>>> p.id52>>> p.name = 'Apress Publishing'>>> p.save()

o.save()

1

Page 199: Django

UPDATE

>>> Publisher.objects.all().update(country='USA')2

>>> ...>>> p.id52>>> p.name = 'Apress Publishing'>>> p.save()

o.save()

queryset.update(...)

1

n

Page 200: Django

DELETE

Page 201: Django

DELETE

>>> ...>>> p.id52>>> p.delete()

o.delete()

1

Page 202: Django

DELETE

>>> ps = Publisher.objects.all()>>> ps.delete()

>>> ...>>> p.id52>>> p.delete()

o.delete()

queryset.delete()

1

n

Page 203: Django

SELECT  de  1  resultado

Page 204: Django

SELECT  de  1  resultado

>>> Publisher.objects.get(name="Apress")<Publisher: Apress>

.get(...)

Page 205: Django

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.

Page 206: Django

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.

Page 207: Django

SELECT  de  N  resultados

Page 208: Django

SELECT  de  N  resultados

>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: O'Reilly>]

.all()

Page 209: Django

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(...)

Page 210: Django

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(...)

Page 211: Django

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!

Page 212: Django

get(),  filter()  y  exclude()

Page 213: Django

get(),  filter()  y  exclude()

Modelo.objects.filter(campo1="valor1", campo2="valor2")

Los  parámetros  pueden  indicar  mucho  más  que  igualdad  (=)

Page 214: Django

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

Page 215: Django

ORDER  BY

Page 216: Django

ORDER  BY

>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]

.order_by(...)

Page 217: Django

ORDER  BY

>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: O'Reilly>]

.order_by(...)

>>> Publisher.objects.order_by("-name")[<Publisher: O'Reilly>, <Publisher: Apress>]

Page 218: Django

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úl0ples  campos:

Page 219: Django

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úl0ples  campos:

¡También  

devuelve  

QuerySets!

Page 220: Django

Slicing

Page 221: Django

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>]

Page 222: Django

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

Page 223: Django

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

Page 224: Django

Related  Objects

Page 225: Django

Related  ObjectsOneToOneField

class Coche(models.Model): motor = OneToOneField(Motor)

class Motor(models.Model): ...

1

1

Page 226: Django

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

Page 227: Django

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

Page 228: Django

Related  Objects

Page 229: Django

Related  ObjectsForeignKeyField

class Blog(models.Model): ...

class Post(models.Model): blog = ForeignKeyField(Blog)

1

n

Page 230: Django

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

Page 231: Django

Related  Objects

Page 232: Django

Related  ObjectsManyToManyField

class Post(models.Model): tags = ManyToManyField(Tag)

class Tag(models.Model): ...

n

m

Page 233: Django

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

Page 234: Django

Related  Objects

Page 235: Django

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

Page 236: Django

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

Page 237: Django

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

Page 238: Django

Y  la  guinda  final:  ¡Todo  es  LAZY!

Page 239: Django

Laziness

Page 240: Django

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'):

Page 241: Django

CRUD:  Create,  Retrieve,  Update  &  Delete

Page 242: Django

django.contrib.admin

1

2

3

Page 243: Django

django.contrib.admin

1

2

3

Page 244: Django

django.contrib.admin

1

Page 245: Django

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('',

...

# url(r'^admin/', include(admin.site.urls)),

...

)

1

2

urls.py

Page 246: Django

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('',

...

url(r'^admin/', include(admin.site.urls)),

...

)

1

2

urls.py

Page 247: Django

Django  admin:  Instalación

INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'django.contrib.admin', ...)

seungs.py

1

Page 248: Django

Actualizando  la  BD

Page 249: Django

Actualizando  la  BD

$ python manage.py syncdb

Creating table django_admin_log

Installing index for admin.LogEntry model

Admin  lista  para  usar

Page 250: Django

¿Y  nuestra  app?

?

Page 251: Django

¿Y  nuestra  app?

Page 252: Django

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)

Page 253: Django

1,2,3  Borrar  la  BD....  1,2,3...  Borrar  la  BD

Page 254: Django

Fixtures

Page 255: Django

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:

Page 256: Django

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 ...>

Page 257: Django

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  u0lizando:

python manage.py loaddata <fixture fixture ...>

•  Si  se  llaman  ini<al_data  y  están  dentro  de  la  carpeta  fixtures  de  la  app,  se  cargan  al  ahcer  el  syncdb.

Page 258: Django

Formularios

Page 259: Django

Clases  involucradas

Page 260: Django

Clases  involucradas

Widget Componente  visual  equivalente  a  HTMLTextInput

CheckboxInput

<input type='text'...>

<input type='checkbox'...>

Page 261: Django

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, ...

Page 262: Django

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, ...]

Page 263: Django

Fields

Page 264: Django

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

Page 265: Django

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

Page 266: Django

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

Page 267: Django

Creación  de  un  Form

from django.shortcuts import render

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(request, 'contact_form.html', {'form': form})

• Paso  3/3:  Programación  de  la  vista  en  views.py

Page 268: Django

Creación  de  un  Form

from django.shortcuts import render

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(request, 'contact_form.html', {'form': form})

• Paso  3/3:  Programación  de  la  vista  en  views.py

Pa_ern

Page 269: Django

Creación  de  un  Form

from django.shortcuts import render

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(request, 'contact_form.html', {'form': form})

• Paso  3/3:  Programación  de  la  vista  en  views.py

Pa_ern

Page 270: Django

Creación  de  un  Form

from django.shortcuts import render

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(request, 'contact_form.html', {'form': form})

• Paso  3/3:  Programación  de  la  vista  en  views.py

Pa_ern

Page 271: Django

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>:

Page 272: Django

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>:

Page 273: Django

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:

Page 274: Django

Forms  a  par0r  de  Models:  El  COLMO  del  DRY

Page 275: Django

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

Page 276: Django

Magia  avanzada

Page 277: Django

ROSA

Page 278: Django

NUNCA

ROSA

Page 279: Django

NUNCAINFRAVALORÉIS

ROSA

Page 280: Django

NUNCAINFRAVALORÉIS

EL  PODER

ROSA

Page 281: Django

NUNCAINFRAVALORÉIS

EL  PODERDE  UN  PONYROSA

Page 282: Django

Views  avanzadasGeneric  Views

Vistas  con  funcionalidad  genérica  parametrizable  mediante  un  diccionario  de  Extra  Op-ons

from django.conf.urls.defaults import *from mysite import views

urlpatterns = patterns('', url(r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}), url(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}),)

Las  tuplas  de  pa>erns()  pueden  tener  3  elementos

Page 283: Django

Views  avanzadas

Renderiza  directamente  la  template  indicada

from django.conf.urls.defaults import *from django.views.generic.simple import direct_to_template

urlpatterns = patterns('', url(r'^about/$', direct_to_template, {'template': 'about.html'}))

from django.views.generic.simple import direct_to_template

Es  la  Generic  View  más  simple  y  más  u+lizada

Page 284: Django

Template  LibraryNos  permite  extender  el  sistema  de  templates  

de  Django  con  Filters  y  Tags  propios

Page 285: Django

Template  LibraryNos  permite  extender  el  sistema  de  templates  

de  Django  con  Filters  y  Tags  propios

Uso

{% load milibreria %}

...

{{ variable|mifiltro:"param" }}

...

{% mitag param1 param2 %}

Page 286: Django

Template  LibraryNos  permite  extender  el  sistema  de  templates  

de  Django  con  Filters  y  Tags  propios

Uso

{% load milibreria %}

...

{{ variable|mifiltro:"param" }}

...

{% mitag param1 param2 %}

Creación

Page 287: Django

Custom  FiltersUn  Filter  es  una  función  Python  que:

• Recibe  1  o  2  argumentos:  (value  [,  arg]).

• Siempre  devuelve  algo:  el  resultado,  value  o  "".

• Falla  silenciosamente:  no  lanza  excepciones.

Page 288: Django

Custom  FiltersUn  Filter  es  una  función  Python  que:

• Recibe  1  o  2  argumentos:  (value  [,  arg]).

• Siempre  devuelve  algo:  el  resultado,  value  o  "".

• Falla  silenciosamente:  no  lanza  excepciones.

from django import template

register = template.Library()

def cut(value, arg=' '): return value.replace(arg, '') register.filter('cut', cut)

Ejemplo

Page 289: Django

Custom  FiltersUn  Filter  es  una  función  Python  que:

• Recibe  1  o  2  argumentos:  (value  [,  arg]).

• Siempre  devuelve  algo:  el  resultado,  value  o  "".

• Falla  silenciosamente:  no  lanza  excepciones.

from django import template

register = template.Library()

@register.filter(name='cut')def cut(value, arg=' '): return value.replace(arg, '')

Page 290: Django

Python  

2.4  se  hizo  

sexy

Custom  FiltersUn  Filter  es  una  función  Python  que:

• Recibe  1  o  2  argumentos:  (value  [,  arg]).

• Siempre  devuelve  algo:  el  resultado,  value  o  "".

• Falla  silenciosamente:  no  lanza  excepciones.

from django import template

register = template.Library()

@register.filter(name='cut')def cut(value, arg=' '): return value.replace(arg, '')

Page 291: Django

Custom  TagsEl  método  genérico  para  crear  Tags  es  complejo.

Vamos  a  ver  cómo  crear  los  2  +pos  de  Tags  más  sencillos:

SimpleTags InclusionTags

• Son  inline

• Reciben  1  argumento

• Devuelven  un  string

• Son  inline

• Reciben  n  argumentos

• Devuelven  un  diccionario

• Insertan  su  propio  

fragmento  de  template

Page 292: Django

SimpleTagsEjemplo:  Devolver  la  hora  actual  formateada.

{% current_time "%Y-%m-%d %I:%M %p" %}

Page 293: Django

SimpleTagsEjemplo:  Devolver  la  hora  actual  formateada.

{% current_time "%Y-%m-%d %I:%M %p" %}

from django import template

register = template.Library()

@register.simple_tagdef current_time(format): try: return datetime.datetime.now().strftime(str(format)) except UnicodeEncodeError: return ''

Page 294: Django

InclusionTagsEjemplo:  Mostar  anuncios  si  el  usuario  no  es  premium.

{% show_adverts user %}

{% for advert in adverts %} <img src='{{ advert.image }}' />{% endfor %}

adverts.html

milibreria.py

Page 295: Django

InclusionTagsEjemplo:  Mostar  anuncios  si  el  usuario  no  es  premium.

@register.inclusion_tag('website/adverts.html')def show_adverts(user): adverts = [] if not user.profile.is_premium: adverts = Advert.objects.order_by('?').limit(5) return {'adverts': adverts}

{% show_adverts user %}

{% for advert in adverts %} <img src='{{ advert.image }}' />{% endfor %}

adverts.html

milibreria.py

Page 296: Django

MiddlewareNos  permite  escribir  funcionalidad  reu0lizable  que  se  inserta  en  el  flujo  de  ejecución  de  Django

Page 297: 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.""" # ...

Page 298: Django

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',

)

Page 299: Django

Middleware1. Sistema  de  BETA

1. Nos  aseguramos  de  controlar  todas  páginas.

2. Si  el  usuario  +ene  una  IP  o  un  User  o...

2. Si6o  en  Mantenimiento

1. Todo  el  Site  muestra  un  splash  excepto...

3. Cache  Middleware

1. Si  la  vista  cumple  un  patrón  (User  no  logeado,...)  

cacheamos  la  página.

4.  etc...

Page 300: Django

Ofrece  integración  con  la  librería  GNU  ge>ext  de  i18n

1. Un  fichero  .pot  con+ene  todos  los  strings  usados

contabilidad.pot

2. En  cada  fichero  .po  se  guarda  una  traducción

es_ES.pot      es_AR.pot      en_GB.pot

3. Cada  .po  se  compila  y  genera  un  .mo  binario

es_ES.mo      es_AR.mo      en_GB.mo

Internacionalización

Page 301: Django

Internacionalización

• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?

• Ges+ón  cómoda  de  singulares  y  plurales

Page 302: Django

Internacionalización

from django.utils.translation import ugettext as _

print _("Cadena de texto")

• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?

• Ges+ón  cómoda  de  singulares  y  plurales

Page 303: Django

Internacionalización

from django.utils.translation import ugettext as _

print _("Cadena de texto")

• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?

from django.utils.translation import ungettext

frase = ungettext("Hay %(total)d resultado", "Hay %(total)d resultados", total) % { 'total': total }

• Ges+ón  cómoda  de  singulares  y  plurales

Page 304: Django

caching

•Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache!

•Recomendado  =  memcached

•Acceder  a  la  BD  es  caro,  muy  caro.

•El  Hardware  es  “gra0s”  en  comparación  con  op0mizar  código  op0mizado.

•Ejemplo  (Facebook):

Page 305: Django

caching

•Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache!

•Recomendado  =  memcached

•Acceder  a  la  BD  es  caro,  muy  caro.

•El  Hardware  es  “gra0s”  en  comparación  con  op0mizar  código  op0mizado.

•Ejemplo  (Facebook):

300+Tb  Memcached

Page 306: Django

caching

from django.views.decorators.cache import cache_page

@cache_page(60 * 15)def my_view(request): ...

views

Page 307: Django

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

Page 308: Django

caching

low  level

Page 309: Django

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  0po  de  objeto  que  se  pueda  serializar.

•  QuerySets•  Listas•  ...

Page 310: Django

Deploying  Django

1. h_p://virtualenv.openplans.org/

2. h_p://pip.openplans.org/

Page 311: Django

Deploying  Django

Virtualenv  +  PIP  1. h_p://virtualenv.openplans.org/

2. h_p://pip.openplans.org/

Page 312: Django

Virtualenv

•Independencia  completa  de  las  librerías  del  sitema.

•Cada  proyecto  0ene  su  juego  de  librerías  en  la  versión  que  necesita•Sin  miedo  a  actualizar

•Sin  miedo  a  migrar

•etc...

Page 313: Django

Virtualenv

•Independencia  completa  de  las  librerías  del  sitema.

•Cada  proyecto  0ene  su  juego  de  librerías  en  la  versión  que  necesita•Sin  miedo  a  actualizar

•Sin  miedo  a  migrar

•etc...

$ virtualenv mi_entorno

crear

Page 314: Django

Virtualenv

•Independencia  completa  de  las  librerías  del  sitema.

•Cada  proyecto  0ene  su  juego  de  librerías  en  la  versión  que  necesita•Sin  miedo  a  actualizar

•Sin  miedo  a  migrar

•etc...

$ virtualenv mi_entorno

crear

$ source mi_entorno/bin/activate

ac-var

Page 315: Django

PIP

•Gestor  de  paquetes  del  siglo  21  :D•Permite  especificar  un  fichero  de  REQUIREMENTS  con  un  listado  de  paquetes  a  instalar.

Page 316: Django

PIP

•Gestor  de  paquetes  del  siglo  21  :D•Permite  especificar  un  fichero  de  REQUIREMENTS  con  un  listado  de  paquetes  a  instalar.

Django==1.4psycopg2feedparser==4.1stripogram==1.5GChartWrapper==0.8

pip install -E mi_entorno -r REQUIREMENTS

Page 317: Django

El  Stack

Page 318: Django

nginx  +  Gunicorn

nginx

gunicorn

•  nginx  [engine  x]  is  a  HTTP  and  reverse  proxy  server.•  Con  una  configuración  muy  sencilla  podremos  u0lizarlo  como  proxy  inverso  a  gunicorn.

•  hSp://gunicorn.org/

•  Servidor  Web  WSGI  implementado  en  Python•  Facilidades  de  puesta  en  marcha  de  proyectos  django•  Fácilmente  configurable  usando  nginx•  hSp://nginx.org/

Page 319: Django

nginx  :80

gunicorn

Django

WSGI  Server

Frontend

Deploysencillo

worker  1 worker  2 worker  n

Page 320: Django

gunicorn

Django

nginx  :80

web1

gunicorn

Django

nginx  :80

web2

gunicorn

Django

nginx  :80

webn

nginx  :80  :443

varnish

haproxy

frontend1

nginx  :80  :443

varnish

haproxy

frontend2

ipfailover

Deployno  tan  sencillo

Page 321: Django

Fabric

Page 322: Django

Repe00on  leads  to  boredom,boredom  to  horrifying  mistakes,horrifying  mistakes  to  God-­‐I-­‐wish-­‐I-­‐was-­‐s0ll-­‐bored.

Page 323: Django

$ fab deploy -R test

Page 324: Django

$ fab deploy -R www

Page 325: Django

Magia  avanzada

1. Views  avanzadas

2. Context  Processors

3. Custom  Template  Filters  &  Tags

4.Middleware

5. Internacionalización

6. Caching

7. Despliegue

8. Apps  recomendadas

Page 326: Django

Apps

Page 327: Django

django-­‐south

Page 328: Django

django-­‐south

•  Sistema  inteligente  para  realizar  de  manera  automá0ca  migraciones  de  esquemas.

•¿Que  sucede  si  tengo  un  Modelo  con  100.000  filas  y  quiero  añadir  una  columna?  ...  south!

•Necesito  migrar  el  contenido  desde  mi  an0guo  Modelo  a  uno  nuevo...  south!

•Necesito  que  ...  south!

hSp://south.aeracode.org/

Page 329: Django

django-­‐south

$ python manage.py schemamigration website --initial

crear  primer  schema

$ python manage.py schemamigration website --auto

crear  2-­‐*  migración

$ python manage.py migrate

aplicar  migraciones

Page 330: Django

django-­‐southhSp://south.aeracode.org/

$ python manage.py schemamigration website --initial

crear  primer  schema

$ python manage.py schemamigration website --auto

crear  2-­‐*  migración

$ python manage.py migrate

aplicar  migraciones

Page 332: Django

django-­‐haystack

•  “EL”  Sistema  de  búsquedas  para  Django

•  Funciona  con  varios  sistemas  de  Indexación

•  Solr,  Xapian,  Whoosh

•  Features:

•  ‘More  like  this’

•Face0ng

•Highligh0ng

•  Spelling  Sugges0on

•  etc...

 h>p://haystacksearch.org

Page 333: Django

django-­‐registra-on

 h>p://bitbucket.org/ubernostrum/django-­‐registra-on/

Page 334: Django

django-­‐registra-on

•Sistema  completo  para  la  ges0ón  de  usuarios.

•Desde  el  registro,  ac0vación  etc...

•DRY!!

•Instalación  muy  sencilla.

 h>p://bitbucket.org/ubernostrum/django-­‐registra-on/

Page 335: Django

django-­‐registra-on

 h>p://bitbucket.org/ubernostrum/django-­‐registra-on/

Page 336: Django

django-­‐registra-on/ac0vate/complete//ac0vate/<ac0va0on_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//  reac0vate/

 h>p://bitbucket.org/ubernostrum/django-­‐registra-on/

Page 337: Django

django-­‐debug-­‐toolbar

 h>p://github.com/robhudson/django-­‐debug-­‐toolbar

Page 339: Django

•Sistema  de  Tareas  Asíncronas  distribuidas.

•Features:  Colas,  Concurrencia,  Distribuido...

•Muy  fácil  implementación  y  escalable.

•Casos  prác-cos:

•Enviar  un  email

•Calcular  el  karma  de  de  los  usuarios  del  sistema.

•Tareas  programadas  (Limpieza,  Post-­‐procesado,  etc...)

Celery

 h>p://celeryproject.org

Page 340: Django

from celery.decorators import task

@taskdef add(x, y): return x + y

>>> result = add.delay(4, 4)>>> result.wait() # wait for and return the result8

Celery

 h>p://celeryproject.org

Page 341: Django

from celery.decorators import task

@taskdef add(x, y): return x + y

>>> result = add.delay(4, 4)>>> result.wait() # wait for and return the result8

• Las  Task  son  simples  funciones  (O  class  si  queremos)

• Python  100%  el  retorno  será  el  resultado

• Usamos  el  decorador  @task  para  registrarla

• El  método  .delay  sobre  cualquier  Task  lo  

ejecuta  en  background.

• Podemos  esperar  a  que  un  Worker  ejecute  

la  tarea  o  seguir  haciendo  otras  acciones.

Celery

 h>p://celeryproject.org

Page 342: Django

Sublime  Text  2

 h>p://www.sublimetext.com/2

Page 344: Django

La  punta  del  iceberg

Page 346: Django

How  to  ...  using  Django?

Page 347: Django

Recommended