Desarrollo web ágil con Python y Django
Upcoming SlideShare
Loading in...5
×
 

Desarrollo web ágil con Python y Django

on

  • 8,042 views

Curso de Python y Django impartido con Jorge Bastida para Bizkaia Enpresa Digitala en el European Software Institute de Zamudio, enero 2011.

Curso de Python y Django impartido con Jorge Bastida para Bizkaia Enpresa Digitala en el European Software Institute de Zamudio, enero 2011.

Statistics

Views

Total Views
8,042
Views on SlideShare
7,791
Embed Views
251

Actions

Likes
14
Downloads
481
Comments
2

11 Embeds 251

http://gc.scalahed.com 69
http://aulavirtual.utel.edu.mx 56
https://twitter.com 43
http://www.pinterest.com 31
http://pinterest.com 19
http://es.pinterest.com 11
http://192.168.10.12 7
https://si0.twimg.com 7
http://www.linkedin.com 5
http://twitter.com 2
http://10.1.47.243 1
More...

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

CC Attribution-ShareAlike LicenseCC Attribution-ShareAlike License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

12 of 2

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • weee naza
    Are you sure you want to
    Your message goes here
    Processing…
  • buenisimo el aporte! gracias =)
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Desarrollo web ágil con Python y Django Desarrollo web ágil con Python y Django Presentation Transcript

    • Jorge  Bas*dame@jorgebas*da.com@jorgebas*daJaime  Irurzunjaime@irurzun.com@jaimeirurzun
    • Jorge  Bas*dame@jorgebas*da.com@jorgebas*daJaime  Irurzun  jaime@irurzun.com@jaimeirurzun
    • Evaluación
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • • Legible• Produc/vo• Portable• Extenso• Integrable• ...  y  Diver/doSintaxis  intuiHva  y  estrictaEntre  1/3  y  1/5  más  conciso  que  Java  o  C++GNU/Linux,  Windows,  Mac  OS  X,  ...Standard  Library,  Third  parHesC,  C++,  Java,  .NET,  COM,  WS,  CORBA,  ...
    • Instalación$ sudo apt-get install pythonhttp://www.python.org/download/Mountain  Lion  incluye  las  versiones:  2.5.6,    2.6.7, 2.7.2
    • El  Intérprete
    • El  Intérprete$ python holamundo.pyhola 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  Interac*vo$ python holamundo.pyhola mundo!$Modo  Batch#!/usr/bin/env pythonprint "hola mundo!"holamundo.py
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35Llong
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falsebool
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str[1, [2, three], 4]list
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str[1, [2, three], 4]list{food: spam, taste: yum}dict
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str[1, [2, three], 4]list{food: spam, taste: yum}dict(1, spam, 4, U)tuple
    • Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str[1, [2, three], 4]list{food: spam, taste: yum}dict(1, spam, 4, U)tuple¡Tipado  dinámico!
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Operadores  h@p://docs.python.org/library/operator.html
    • Operadoresnuméricosa + b a - b a * b a / ba % b -a +a a ** b  h@p://docs.python.org/library/operator.html
    • Operadoresnuméricosa + b a - b a * b a / ba % b -a +a a ** bcomparadoresa < b a <= b a > ba >= b a == b a != b  h@p://docs.python.org/library/operator.html
    • Operadoresnuméricosa + b a - b a * b a / ba % b -a +a a ** bcomparadoresa < b a <= b a > ba >= b a == b a != blógicos a or b a and b not a  h@p://docs.python.org/library/operator.html
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • 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>>> len(nums)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, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]
    • Usos  frecuentes:  dict>>> user = {nick: neo, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]>>> user[nick]neo>>> user.get(age, 26)26
    • Usos  frecuentes:  dict>>> user = {nick: neo, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]>>> user[nick]neo>>> user.get(age, 26)26>>> nick in userTrue
    • Usos  frecuentes:  dict>>> user = {nick: neo, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]>>> user[nick]neo>>> user.get(age, 26)26>>> nick in userTrue>>> user.update({nick: alatar, age: 25})>>> user{nick: alatar, phone: 5555, 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 % vHycker sabe 5 idiomas
    • juego/__init__.pybonus/__init__.pyestrella.pymoneda.pyplanta.py...personajes/__init__.pymario.pyluigi.pyprincesa.py...enemigos/__init__.pyseta.pytortuga.pybomba.py...Módulos1. Un  módulo  es  un  fichero  .py2. Los  módulos  pueden  organizarse  en  paquetes.3. Un  paquete  es  una  carpeta  que  conHene  un  fichero  con  nombre  __init__.py
    • juego/__init__.pybonus/__init__.pyestrella.pymoneda.pyplanta.py...personajes/__init__.pymario.pyluigi.pyprincesa.py...enemigos/__init__.pyseta.pytortuga.pybomba.py...Módulos1. Un  módulo  es  un  fichero  .py2. Los  módulos  pueden  organizarse  en  paquetes.3. Un  paquete  es  una  carpeta  que  conHene  un  fichero  con  nombre  __init__.py123
    • MódulosEn  la  lista  de  directorios  que  conHene  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ódulosjuego/__init__.pybonus/__init__.pyestrella.pymoneda.pyplanta.py...personajes/__init__.pymario.pyluigi.pyprincesa.py...enemigos/__init__.pyseta.pytortuga.pybomba.py...
    • Módulosjuego/__init__.pybonus/__init__.pyestrella.pymoneda.pyplanta.py...personajes/__init__.pymario.pyluigi.pyprincesa.py...enemigos/__init__.pyseta.pytortuga.pybomba.py...>>> from juego.personajes.mario import Mario>>> Mario()>>> from juego.personajes.mario import *>>> Mario()>>> from juego import personajes>>> personajes.mario.Mario()
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • {}Estructuras
    • {}Estructuras
    • >>> from __future__ import bracesFile "<stdin>", line 1SyntaxError: not a chanceIdentación4  Espac/os  para  la  identación
    • >>> from __future__ import bracesFile "<stdin>", line 1SyntaxError: not a chanceIdentación4  Espac/os  para  la  identaciónPEP 8
    • •  Guido  van  Rossum  (2001)•  Recomendaciones  de  esHlo•  “Readability  counts”•  “Code  is  read  much  more  ohen  than  it  is  wriien.”•  Muy  recomendable  importante  seguirlo.PEP 8¿PEP  8?  h@p://www.python.org/dev/peps/pep-­‐0008/
    • def my_first_function(p1, p2):return "Hello World!"FuncionesMinúsculasPalabras  separadas  por  _Evitar  camelCase
    • def my_first_function(p1, p2):return "Hello World!"123FuncionesMinúsculasPalabras  separadas  por  _Evitar  camelCasePEP 8
    • Conversión  de  /pos  h@p://docs.python.org/library/func/ons.html
    • Conversión  de  /pos>>> int(1.3)1  h@p://docs.python.org/library/func/ons.html
    • Conversión  de  /pos>>> str(2)2>>> int(1.3)1  h@p://docs.python.org/library/func/ons.html
    • Conversión  de  /pos>>> str(2)2>>> int(1.3)1>>> float(1)1.0  h@p://docs.python.org/library/func/ons.html
    • 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
    • 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
    • Funciones  comunes  h@p://docs.python.org/library/func/ons.html
    • Funciones  comunes>>> len("Python Mola")11>>> len([1,2,3,4])4  h@p://docs.python.org/library/func/ons.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]  h@p://docs.python.org/library/func/ons.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>  h@p://docs.python.org/library/func/ons.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...  h@p://docs.python.org/library/func/ons.html
    • Funciones  interesantesSon  sólo  un  ejemplo...  h@p://docs.python.org/library/func/ons.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...  h@p://docs.python.org/library/func/ons.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...  h@p://docs.python.org/library/func/ons.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...  h@p://docs.python.org/library/func/ons.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...  h@p://docs.python.org/library/func/ons.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 stringReturn those items of sequence for which function(item) is true. Iffunction is None, return the items that are true. If sequence is a tupleor string, return the same type, else return a list.(END)
    • class Student(object):def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.nameClasess = Student("Jorge", 24)camelCase
    • class Student(object):def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.name1 2345Clasess = Student("Jorge", 24)camelCasePEP 8
    • El  operador  ()• Es  importante  diferenciar:funcion      vs      funcion()Clase              vs        Clase()• El  operador  ()  permite:• Invocar  funciones:• Instanciar  clases:resultado = funcion()objeto = Clase("param1")
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • $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" % countcount+=1Sentencias:  while
    • for ($i=0; $i < 5; $i++) {echo "Number ".$count;}for i in range(4):print "Number %i" % countSentencias:  for
    • try {$result = 3 / 0;} catch (Exception $e) {echo "Division by Zero"}try:result = 3 / 0except:print "Division by Zero"Sentencias:  try-­‐except
    • Prueba  de  sentencias  en  consola
    • •  Python  es  un  lenguaje  fácil  de  aprender.•  Menos  código:•  Muchos  Muchísimos  menos  errores  de  Sintaxis.•  Mayor  velocidad  de  escritura.•  ProtoHpado...  UHlizado  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.•  ProtoHpado...  UHlizado  por  grandes  empresas.etc...Conclusiones
    • Ejemplo  PythonhGp://bit.ly/ejemplo-­‐python    
    • Ejercicio  PythonhGp://bit.ly/ejercicio-­‐python    
    • SolucioneshGp://bit.ly/ejercicio-­‐resueltohGp://bit.ly/ejercicio-­‐resuelto-­‐awesome
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Evolución  de  la  WebDesarrollo  Web1ª  Generación 2ª  Generación 3ª  GeneraciónHTMLCGIPHPASPJSP...DjangoRailsSymfony...
    • 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)Filoso]a
    • •  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 inone, and only one, place. Redundancy is bad.Normalization is good.”“Filoso]a
    • •  Explicit  is  beier  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/
    • La  comunidad
    • La  comunidad• django-­‐users23.000  miembros• django-­‐developers7.400  miembros• djangoproject.com+500.000  visitas  únicas  mensuales
    • ¿Quién  usa  Django?
    • ¿Quién  usa  Django?
    • 1.  Instalación  Python$ sudo apt-get install pythonhttp://www.python.org/download/Mountain  Lion  incluye  las  versiones:  2.5.6,  2.6.7, 2.7.2
    • Configurar  un  motor  de  Base  de  Datos:•  Oficiales:  •  PostgreSQL•  MySQL•  Oracle•  SQLite•  Comunidad:  •  Sybase  SQL  Anywhere•  IBM  DB2•  Microsoh  SQL  Server  2005•  Firebird•  ODBC2.  Instalación  SGBD
    • Configurar  un  motor  de  Base  de  Datos:•  Oficiales:  •  PostgreSQL•  MySQL•  Oracle•  SQLite•  Comunidad:  •  Sybase  SQL  Anywhere•  IBM  DB2•  Microsoh  SQL  Server  2005•  Firebird•  ODBC2.  Instalación  SGBD
    • •  Vamos  a  uHlizar  SQLite  por  comodidad•  Desde  Python  2.5  podemos  uHlizar  sqlite    sin  instalar  nada.2.  Instalación  SGBD
    • •  Vamos  a  uHlizar  SQLite  por  comodidad•  Desde  Python  2.5  podemos  uHlizar  sqlite    sin  instalar  nada.2.  Instalación  SGBD
    • A:  Paquetes  de  cada  distro• apt-get install python-djangoB:  Official  Release• http://www.djangoproject.com/download/• python setup.py installC:  Github• git clone https://github.com/django/django.git3.  Instalación  Django
    • All  Right?
    • All  Right?>>> import django>>> django.VERSION(1, 4, 2, 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  proyectoFicheros  y  Carpetas¿Es  Django  tán  simple  y  fácil  de  usar?
    • *  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
    • Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
    • Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
    • Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasDjango52FicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
    • Let’s  enjoy
    • Crear  nuestro  proyectode  5  ficheros  ;-­‐)
    • Crear  nuestro  proyecto$ django-admin.py startproject dwitterde  5  ficheros  ;-­‐)
    • Crear  nuestro  proyecto$ django-admin.py 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  ;-­‐)
    • sesngs.py
    • Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)
    • Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)$ cd dwitter$ python manage.py runserverValidating models...0 errors foundDjango version 1.4, using settings dwitter.settingsDevelopment server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.
    • Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)$ cd dwitter$ python manage.py runserverValidating models...0 errors foundDjango version 1.4, using settings dwitter.settingsDevelopment server is running at http://127.0.0.1:8000/Quit the server with CONTROL-C.
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • MVC  en  DjangoModelo  =  Model Vista  =  Template Controlador  =  URL+View
    • URLs  y  Vistas• El  fichero  urls.py  actúa  como  puerta  de  entrada  para  las  pe*ciones  HTTP• Se  definen  URLs  elegantes  mediante  expresiones  regulares  que  redirigen  a  funciones  de  views.pyurls.pyviews.pyhGp://mysite.com/about/html ...¿urlpaGerns?
    • 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@pResponseviews.pyH@pRequest(),  ...H@pResponse()
    • URLs  y  VistasEjemplo  1:    http://mysite.com/timefrom django.conf.urls.defaults import *from mysite.views import hora_actualurlpatterns = patterns(,url(r^time/$, hora_actual),)from django.http import HttpResponsefrom datetime import datetimedef hora_actual(request):now = datetime.now()html = "Son las %s." % nowreturn HttpResponse(html)urls.pyviews.py
    • URLs  y  Vistasfrom django.conf.urls.defaults import *from mysite.views import dentro_deurlpatterns = patterns(,url(r^time/plus/(d{1,2})/$, dentro_de),)from django.http import HttpResponsefrom datetime import datetime, timedeltadef 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.pyviews.pyEjemplo  2:    http://mysite.com/time/plus/2
    • URLs  y  Vistasfrom django.conf.urls.defaults import *from mysite.views import dentro_deurlpatterns = patterns(,url(r^time/plus/(d{1,2})/$, dentro_de),)from django.http import HttpResponsefrom datetime import datetime, timedeltadef 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.pyviews.pyEjemplo  2:    http://mysite.com/time/plus/2
    • ¡Recuerda!:  MVC
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • 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  *pos  de  objetos:  Template()  y  Context().• Un  objeto  Template()  con*ene  el  string  de  salida  que  queremos  devolver  en  el  HGpResponse  (normalmente  HTML),  pero  incluyendo  e*quetas  especiales  de  Django.• Un  objeto  Context()  con*ene  un  diccionario  con  los  valores  que  dan  contexto  a  una  plan*lla,  los  que  deben  usarse  para  renderizar  un  objeto  Template()."Bienvenido, {{ user }}."{user: alatar}Template:Context:"Bienvenido, alatar."
    • Templatesfrom django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetimePLANTILLA = """<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  obje*vo:  Template  +  Context
    • Templates• Segunda  aproximación  al  obje*vo:  open(),  read(),  close()from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetimedef 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  obje*vo:  open(),  read(),  close()from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetimedef 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  obje*vo:  open(),  read(),  close()from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetimedef 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  obje*vo:  get_template()from django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetimedef 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,)senngs.py
    • Templates• Tercera  aproximación  al  obje*vo:  get_template()TEMPLATE_DIRS = (/home/django/templates,)senngs.pyfrom django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetimedef 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  obje*vo:  get_template()TEMPLATE_DIRS = (/home/django/templates,)senngs.pyfrom django.http import HttpResponsefrom django.template.loader import get_templatefrom django.template import Contextfrom datetime import datetimedef hora_actual(request):now = datetime.now()t = get_template(hora.html)c = Context({hora: now})html = t.render(c)return HttpResponse(html)S*ll  boring...
    • Templates• Obje*vo  alcanzado:  render()from django.shortcuts import renderfrom datetime import datetimedef hora_actual(request):now = datetime.now()return render(request, hora.html, {hora: now})
    • Templates• Obje*vo  alcanzado:  render()from django.shortcuts import renderfrom datetime import datetimedef hora_actual(request):now = datetime.now()return render(request, hora.html, {hora: now})Boring...?
    • Templates• Obje*vo  alcanzado:  render()from django.shortcuts import renderfrom datetime import datetimedef hora_actual(request):now = datetime.now()return render(request, hora.html, {hora: now})AWESOME!
    • Templates:  TipTEMPLATE_DIRS = (/home/django/templates,)senngs.pya)
    • Templates:  TipTEMPLATE_DIRS = (/home/django/templates,)senngs.py Reusable  apps?a)
    • Templates:  TipTEMPLATE_DIRS = (/home/django/templates,)senngs.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.Loader,django.template.loaders.app_directories.Loader,)return render(request, website/index.html)Alterna*va  reu*lizable:
    • ¡Empieza  nuestro  primer  proyecto!a) Crear  la  app  dwiier.website.b)Incluir  la  app  en  sesngs.py.c) Definir  una  vista  para  la  URL  “/”  que  devuelva  el  texto:        “Welcome  to  dwiier!”:‣ /‣ timeline(request)
    • h@p://github.com/enjoydjango/dwi@er
    • Git
    • GitQuiero  ir  a...¿Donde  estoy?1ª
    • Git$ git clone https://github.com/enjoydjango/dwitter.git$ git checkout -t origin/step-01-viewsQuiero  ir  a...$ git branch¿Donde  estoy?$ git checkout step-01-views1ª
    • GitIgnorar  todos  los  cambios  **  Si  no  habéis  commiteado  nada
    • Git$ git reset --hard HEAD$ git clean -fdIgnorar  todos  los  cambios  **  Si  no  habéis  commiteado  nada
    • h@p://github.com/enjoydjango/dwi@er
    • Tarea:  URLs  y  Vistasa) Implementar  la  vista  timeline()  para  que  renderice  un  Hmeline  de  twiier  en  una  template  index.html  a  parHr  de  datos  hardcodeados  en  un  diccionario.  h@p://bit.ly/diccionario-­‐tweets
    • 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
    • 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.
    • 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 %}commentfor {% for elemento in lista %}<li>{{ elemento }}<li>{% endfor %}
    • Templates:  tags  {%  %}{% comment %} Bu! {% endcomment %}commentfor {% for elemento in lista %}<li>{{ elemento }}<li>{% endfor %}if {% if username == "Juan" %}Hola Juan, me gustas!{% else %}Hola {{ username }},{% endif %}== != > < >= <=in and or not
    • 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:  Tagsa) UHlizar  tags  para  que  el  Hmeline  se  muestre  con  el  siguiente  formato:• <username>:  <tweet>  <Hmestamp>• <username>:  <tweet>  <Hmestamp>• ...
    •  Tarea:  Tags  avanzadosa) Hacer  que  el  Hmeline  muestre  el  mensaje  “No  hay  tweets.”  si  el  diccionario  recibido  está  vacío.
    • 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 }}striptagsJuan es majo guapo y listo
    • Templates:  Filters{username: Juan es <b>majo, guapo y <em>listo</em></b>}{{ username|striptags }}striptagsJuan es majo guapo y listo{{ username|truncatewords_html:4 }}truncatewords_htmlJuan es <b>majo guapo</b> ...
    • Templates:  Filters{username: Juan es <b>majo, guapo y <em>listo</em></b>}{{ username|striptags }}striptagsJuan es majo guapo y listo{{ username|truncatewords_html:4 }}truncatewords_htmlJuan es <b>majo guapo</b> ...{{ username|removetags:”em a br” }}removetagsJuan es <b>majo guapo y listo</b>
    • Templates:  Filters
    • Templates:  Filters{url: Visitad http://www.djangoproject.com}{{ url|urlize }}urlizeVisitad <a href=”http://www.djangoproject.com”> http://www.djangoproject.com </a>
    • Templates:  Filters{url: Visitad http://www.djangoproject.com}{{ url|urlize }}urlizeVisitad <a href=”http://www.djangoproject.com”> http://www.djangoproject.com </a>{{ url|urlizetrunc:16 }}urlizetruncVisitad <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:  Filtersa) Añadir  a  cada  tweet  del  Hmeline  el  Hempo  transcurrido:• <username>:  <tweet><n>  seconds  ago• <username>:  <tweet><n>  minutes  ago• ...
    • Tarea:  Filtersb)Formatear  las  publicaciones  de  HOYGANs  convirHendo  el  texto  a  minúsculas  capitalizadas:‣“HOYGAN  NESESITO  QUE  MAYUDEN  A  HASER  UN  PROGRAMA  EN  DJANGO  GRASIAS  DE  ANTEBRASO”‣“Hoygan  necesito  que  mayuden  a  haser  un  programa  en  django  grasias  de  antebraso”  
    • Tarea:  Filtersc) Conseguir  que  todas  las  urls  que  aparezcan  en  los  tweets  se  conviertan  en  enlaces  <a  href=...  />  de  HTML.
    • Herencia  de  Templatesbase.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:  Herencia  de  templatesa) Descargar  nuestra  template  base.html.b)Incluirla  en  vuestra  app.c) Hacer  que  vuestro  index.html  herede  de  base.html  y  exHenda  el  bloque  ‘content’  con  su  contenido.  h@p://bit.ly/base-­‐html-­‐template
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Modelos
    • ¿SQL?
    • Ejemplo  SQLdef 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  SQLdef 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})123456
    • 12  lineas  de  Python...  ¬_¬
    • ORM  (Object-­‐RelaHonal  mapping)
    • ORM  (Object-­‐RelaHonal  mapping)
    • Ejemplo  ORMdef book_list(request):names = Books.objects.all().order_by(name)return render(request, book_list.html, {names:names})
    • Ejemplo  ORMdef book_list(request):names = Books.objects.all().order_by(name)return render(request, book_list.html, {names:names})1 2
    • Fucking  Ninjas!
    • Modelofrom django.db import modelsclass 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 modelsclass Books(models.Model):name = models.CharField(blank=True, max_length=100)created = models.DateTimeField(blank=False)available = models.BooleanField(default=True)213456•  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 websiteBEGIN;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áHcamente.•  <app_name>_lower(<model_name>)•  id  como  Primary  Key  (Personalizable)•  Las  Foreing  Key  terminan  en  _id  (Personalizable)•  Los  Hpos  de  datos  se  ajustan  en  función  del  SGBD
    • Configurar  seyngs.pyDATABASES = {default: {ENGINE: django.db.backends.,NAME: ,USER: ,PASSWORD: ,HOST: ,PORT: ,}}postgresql_psycopg2,postgresql, mysql,sqlite3 or oracle.
    • Configurar  seyngs.pyDATABASES = {default: {ENGINE: django.db.backends.,NAME: ,USER: ,PASSWORD: ,HOST: ,PORT: ,}}123postgresql_psycopg2,postgresql, mysql,sqlite3 or oracle.
    • Creando  Tablas•  Crea  las  tablas  para  todos  los  modelos  de  las  apps  instaladas  en  el  fichero  sesngs.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  sesngs.py•  No  actualiza  esquemas  si  la  tabla  existe.•  Eliminar  tabla  y  volver  a  ejecutar  syncdb
    • Nuestro  primer  modeloa)Crear  modelo  Tweetb)Configurar  sesngs.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_tweetYou just installed Djangos auth system, which means you dont have anysuperusers defined.Would you like to create one now? (yes/no): yesUsername (Leave blank to use neo): adminE-mail address: user@example.comPassword: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_tweetYou just installed Djangos auth system, which means you dont have anysuperusers defined.Would you like to create one now? (yes/no): yesUsername (Leave blank to use neo): adminE-mail address: user@example.comPassword:Password (again):Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet modeldjango.contrib.auth
    • ¿Cuantos  sistemas  de  AutenHcación  habéis  programado?
    • ¿Alguno  era  mejor  que  el  anterior?  ;-­‐)
    • contrib.auth  puede  ser  el  úlHmo  :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_tweetYou just installed Djangos auth system, which means you dont have anysuperusers defined.Would you like to create one now? (yes/no): yesUsername (Leave blank to use neo): adminE-mail address: user@example.comPassword:Password (again):Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet modelwebsite.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_tweetYou just installed Djangos auth system, which means you dont have anysuperusers defined.Would you like to create one now? (yes/no): yesUsername (Leave blank to use neo): adminE-mail address: user@example.comPassword:Password (again):Superuser created successfully.Installing index for auth.Permission modelInstalling index for auth.Message modelInstalling index for website.Tweet modeldjango.contrib.auth
    • BD  Lista  para  usarse
    • BD  Lista  para  usarse
    • Nuestro  primer  modeloa)Hacer  syncdb
    • Previo:  Clases  del  ORMts = Publisher.objects.all()ModelManagerQuerySet
    • 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=OReilly,... 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(...)1n
    • DELETE
    • DELETE>>> ...>>> p.id52>>> p.delete()o.delete()1
    • DELETE>>> ps = Publisher.objects.all()>>> ps.delete()>>> ...>>> p.id52>>> p.delete()o.delete()queryset.delete()1n
    • 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: OReilly>].all()
    • SELECT  de  N  resultados>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: OReilly>].all()>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")[<Publisher: Apress>].filter(...)
    • SELECT  de  N  resultados>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: OReilly>].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: OReilly>].exclude(...)
    • SELECT  de  N  resultados>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: OReilly>].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: OReilly>].exclude(...)¡Devuelven  QuerySets,  no  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|Fcampo__day=31campo__gt=0campo__gte=0campo__lt=0campo__lte=0campo__in=[ ,]campo__month=12campo__startswith=campo__istartswith=campo__endswith=campo__iendswith=campo__range=( ,)campo__year=2010
    • ORDER  BY
    • ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)
    • ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)>>> Publisher.objects.order_by("-name")[<Publisher: OReilly>, <Publisher: Apress>]
    • ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)>>> Publisher.objects.order_by("-name")[<Publisher: OReilly>, <Publisher: Apress>]>>> Publisher.objects.order_by("-name", "country")[<Publisher: OReilly>, <Publisher: Apress>]MúlHples  campos:
    • ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)>>> Publisher.objects.order_by("-name")[<Publisher: OReilly>, <Publisher: Apress>]>>> Publisher.objects.order_by("-name", "country")[<Publisher: OReilly>, <Publisher: Apress>]MúlHples  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: OReilly>]>>> Publisher.objects.order_by("name")[1:2][<Publisher: OReilly>]
    • Slicing>>> Publisher.objects.order_by("name")[0]<Publisher: Apress>[n:m]>>> Publisher.objects.order_by("name")[:2][<Publisher: Apress>, <Publisher: OReilly>]>>> Publisher.objects.order_by("name")[1:2][<Publisher: OReilly>]LIMIT
    • Slicing>>> Publisher.objects.order_by("name")[0]<Publisher: Apress>[n:m]>>> Publisher.objects.order_by("name")[:2][<Publisher: Apress>, <Publisher: OReilly>]>>> Publisher.objects.order_by("name")[1:2][<Publisher: OReilly>]LIMITOFFSET
    • Related  Objects
    • Related  ObjectsOneToOneFieldclass Coche(models.Model):motor = OneToOneField(Motor)class Motor(models.Model):...11
    • Related  ObjectsOneToOneFieldclass 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  nosotros11
    • Related  ObjectsOneToOneFieldclass 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  Django11
    • Related  Objects
    • Related  ObjectsForeignKeyFieldclass Blog(models.Model):...class Post(models.Model):blog = ForeignKeyField(Blog)1n
    • Related  ObjectsForeignKeyFieldclass 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  Django1n
    • Related  Objects
    • Related  ObjectsManyToManyFieldclass Post(models.Model):tags = ManyToManyField(Tag)class Tag(models.Model):...nm
    • Related  ObjectsManyToManyFieldclass 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  Djangonm
    • Related  Objects
    • Related  ObjectsEn  todas  ellas  podemos  renombrar  el  puntero  inversoclass Blog(models.Model):...class Post(models.Model):blog = ForeignKeyField(Blog, related_name=posts)1n
    • Related  ObjectsEn  todas  ellas  podemos  renombrar  el  puntero  inversoclass 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  Django1n
    • Related  ObjectsEn  todas  ellas  podemos  renombrar  el  puntero  inversoclass 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  Django1nCuando  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):
    • Nota:  __unicode__()
    • Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
    • Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
    • Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
    • Nota:  __unicode__()class Publisher(models.Model):...def __unicode__(self):return self.name>>> Publisher.objects.all()[<Publisher: Publisher object>]
    • Nota:  __unicode__()class Publisher(models.Model):...def __unicode__(self):return self.name>>> Publisher.objects.all()[<Publisher: Publisher object>]>>> Publisher.objects.all()[<Publisher: Apress>]
    • Usando  el  ORMa)Insertar  varios  Tweets  desde  la  shell.b)Modificar  views.timeline  para  que  uHlice  los  Tweets  reales  de  la  BD.
    • Usando  el  ORMc) Implementar  la  vista  tweet_page()  como  permalink  de  un  tweet:‣ URL:    tweet/<tweet_id>/‣ View:    tweet_page‣ Template:    tweet_page.html    (Descargar)d)Lanzar  Http404  si  no  existe  el  tweet_id.e)shortcut!:  get_object_or_404()  h@p://bit.ly/tweet-­‐page
    • 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
    • Profileclass Profile(models.Model):user = models.OneToOneField(User, unique=True)bio = models.CharField(blank=True, max_length=200)...models.py•  Cada  objeto  User  de  django.contrib.auth  dispondrá  de  un  atributo  profile  que  nos  permiHrá  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>>>> type(u.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  reuHlizables.•  Permite  subscribirnos  a  “eventos”  a  lo  largo  de  todo  el  framework  y  actuar  frente  a  ellos  (¡Observer-­‐Observable!).•  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
    • Signalsdef create_user_profile(sender, instance, created, **kwargs):if created:Profile.objects.create(user=instance)from django.db.models.signals import post_savepost_save.connect(create_user_profile, sender=User)123Puede  estar  en  cualquier  app  de  nuestro  proyecto.Se  recomienda  models.py
    • Users  en  dwiiera)Crear  el  modelo  Profileb)Crear  signal  para  agregar  un  objeto  Profile  a  cada  objeto  User  creado.c) Eliminar  BD.d)Hacer  syncdb
    • Followers
    • Profilemodels.py
    • Profileclass 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  H,  tú  me  sigues  a  mi.•  related_name  (en  este  caso)•  Limpieza  y  evitar  profile_set
    • Users  en  dwiiera)Añadir  ManyToMany  para  los  followers.b)Eliminar  BD.c) Hacer  syncdb
    • 1,2,3  Borrar  la  BD....  1,2,3...  Borrar  la  BD
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • CRUD:  Create,  Retrieve,  Update  &  Delete
    • django.contrib.admin123
    • django.contrib.admin123
    • django.contrib.admin1
    • Django  admin:  Instalaciónfrom 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)),...)12urls.py
    • Django  admin:  Instalaciónfrom 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)),...)12urls.py
    • Django  admin:  InstalaciónINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,...)senngs.py
    • Django  admin:  InstalaciónINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,django.contrib.admin,...)senngs.py1
    • Actualizando  la  BD
    • Actualizando  la  BD$ python manage.py syncdbCreating table django_admin_logInstalling index for admin.LogEntry modelAdmin  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 adminfrom website.models import Tweetclass TweetAdmin(admin.ModelAdmin):list_display = (id,user,message,timestamp)admin.site.register(Tweet, TweetAdmin)
    • Instalar  Admina)Configurar  urls.pyb)Configurar  sesngs.pyc) Hacer  syncdb
    • Instalar  Admind)Comprobar  que  no  están  Tweet  y  Profilee)Añadir  admin.pyf) Probar  Administración.
    • 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  uHlizando: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.
    • Tarea:  Avance  en  dwiiera)Implementar  la  vista  user_page()  para  ofrecer  un  perfil  de  usuario  con  su  Hmeline  personal:‣ URL:    user/<username>/‣ View:    user_page‣ Template:    user_page.html  h@p://bit.ly/user-­‐page
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Formularios
    • Clases  involucradas
    • Clases  involucradasWidget Componente  visual  equivalente  a  HTMLTextInputCheckboxInput<input type=text...><input type=checkbox...>
    • Clases  involucradasWidget Componente  visual  equivalente  a  HTMLTextInputCheckboxInput<input type=text...><input type=checkbox...>Field Lógica  de  un  campo,  asociado  a  un  WidgetEmailFieldIPAddressFieldwidget, initial, error, ...
    • Clases  involucradasWidget Componente  visual  equivalente  a  HTMLTextInputCheckboxInput<input type=text...><input type=checkbox...>Field Lógica  de  un  campo,  asociado  a  un  WidgetEmailFieldIPAddressFieldwidget, 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  Formfrom django import formsclass 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  Formfrom django.shortcuts import renderfrom mysite.contact.forms import ContactFormdef contact(request):if request.method == POST:form = ContactForm(request.POST)if form.is_valid():cd = form.cleaned_datasend_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
    • Creación  de  un  Formfrom django.shortcuts import renderfrom mysite.contact.forms import ContactFormdef contact(request):if request.method == POST:form = ContactForm(request.POST)if form.is_valid():cd = form.cleaned_datasend_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.pyPaiern
    • Creación  de  un  Formfrom django.shortcuts import renderfrom mysite.contact.forms import ContactFormdef contact(request):if request.method == POST:form = ContactForm(request.POST)if form.is_valid():cd = form.cleaned_datasend_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.pyPaiern
    • Creación  de  un  Formfrom django.shortcuts import renderfrom mysite.contact.forms import ContactFormdef contact(request):if request.method == POST:form = ContactForm(request.POST)if form.is_valid():cd = form.cleaned_datasend_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.pyPaiern
    • Validación  propiafrom django import formsclass 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 messagePodemos  programar  validación  extra  asociada  a  cada  Field  del  formulario  escribiendo  un  método  clean_<fieldname>:
    • Validación  propiafrom django import formsclass 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 messagePodemos  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  parHr  de  Models:  El  COLMO  del  DRY
    • Forms  a  par/r  de  Modelsfrom django.db import modelsclass Author(models.Model):name = models.CharField(max_length=100)birth_date = models.DateField(blank=True, null=True)country = models.ModelChoiceField(Country)...from django import formsfrom books.models import Authorclass AuthorForm(forms.ModelForm):class Meta:model = Authorexclude = (country,)models.pyforms.py
    • Primer  Form  en  dwiiera)Crear  un  Form  que  permita  publicar  tweets  desde  Hmeline.html  al  usuario  que  esté  logueado  desde  django.contrib.admin  (no  tenemos  login  propio  de  momento).
    • Tarea:  Avance  en  dwiiera)Implementar  la  vista  users_list()  para  visualizar  la  lista  de  usuarios:‣ URL:    users/‣ View:    users_list‣ Template:    users_list.html    (Descargar)  h@p://bit.ly/users-­‐list
    • Índice1.Pythona. Introducciónb.Tipos  de  datosc. Operadoresd.Usos  frecuentese. Estructurasf. Sentenciasg. Ejercicio2.Djangoa. Introducciónb.URLs  y  Vistasc. Templatesd.Modeloe. Administraciónf. Formulariosg. Magia  avanzadaProyecto
    • Magia  avanzada
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Views  avanzadasfrom django.conf.urls.defaults import *urlpatterns = patterns(,url(r^hello/$, mysite.views.hello),url(r^time/$, mysite.views.current_datetime),url(r^time/plus/(d{1,2})/$, mysite.views.hours_ahead),)El  primer  parámetro  de  pa@erns()  sirve  de  algo
    • Views  avanzadasfrom django.conf.urls.defaults import *urlpatterns = patterns(,url(r^hello/$, mysite.views.hello),url(r^time/$, mysite.views.current_datetime),url(r^time/plus/(d{1,2})/$, mysite.views.hours_ahead),)from django.conf.urls.defaults import *urlpatterns = patterns(mysite.views,url(r^hello/$, hello),url(r^time/$, current_datetime),url(r^time/plus/(d{1,2})/$, hours_ahead),)¡El  primer  parámetro  de  pa@erns()  sirve  de  algo!
    • Views  avanzadasEn  ficheros  urls.py  que  gesHonen  varias  apps...from django.conf.urls.defaults import *urlpatterns = patterns(mysite.views,url(r^hello/$, hello),url(r^time/$, current_datetime),url(r^time/plus/(d{1,2})/$, hours_ahead),)urlpatterns += patterns(weblog.views,url(r^tag/(w+)/$, tag),)
    • Views  avanzadasEn  ficheros  urls.py  que  gesHonen  varias  apps...from django.conf.urls.defaults import *urlpatterns = patterns(mysite.views,url(r^hello/$, hello),url(r^time/$, current_datetime),url(r^time/plus/(d{1,2})/$, hours_ahead),)urlpatterns += patterns(weblog.views,url(r^tag/(w+)/$, tag),)
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • NUNCAINFRAVALORÉISEL  PODERDE  UN  PONYROSA
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • Views  avanzadas¿Dónde  somos  capaces  de  reu/lizar  código  entre  apps?
    • Views  avanzadasGeneric  ViewsVistas  con  funcionalidad  genérica  parametrizable  mediante  un  diccionario  de  Extra  Op/onsfrom django.conf.urls.defaults import *from mysite import viewsurlpatterns = 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
    • Views  avanzadasRenderiza  directamente  la  template  indicadafrom django.conf.urls.defaults import *from django.views.generic.simple import direct_to_templateurlpatterns = patterns(,url(r^about/$, direct_to_template, {template: about.html}))from django.views.generic.simple import direct_to_templateEs  la  Generic  View  más  simple  y  más  uHlizada
    • Extra  OpHons  en  urls.pya)Definir  dos  nuevas  URLs  en  urls.py  que  se  sirvan  de  las  vistas  de  django.contrib.auth  para  implementar  login  y  logout:‣ URL:    login/‣ View:    auth.views.login‣ Template:    login.html    (Descargar)‣ URL:    logout/‣ View:    auth.views.logout‣ Template:    [redirect a /]  h@p://bit.ly/login-­‐template
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Context  Processors!!!!
    • Context  Processors¿Context  Processors?  Son  funciones.• Reciben  un  HGpRequest()  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  HGpRequest()  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  HGpRequest()  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  ProcessorsEn  lugar  de  encapsular  sólo  el  contexto  de  esta  vista  con  Context,  la  función  render()  instancia  RequestContext,  que  alimenta  nuestro  diccionario  con  todos  los  diccionarios  devueltos  por  los  Context  Processors  que  tengamos  habilitados.def view(request):...return render(request, ...html, {...: ...})def render(request, template, context):t = get_template(template)c = RequestContext(request, context)html = t.render(c)return HttpResponse(html)
    • ContextProcessors  en  dwiierc) Cuando  el  usuario  esté  logueado,  mostrar  Bienvenido,  <username>  y  un  link  para  desloguearse.d)Cuando  no  esté  logueado,  mostrar  un  link  a  /login.e)Tip:  user.is_authenHcated()
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Template  LibraryNos  permite  extender  el  sistema  de  templates  de  Django  con  Filters  y  Tags  propios
    • Template  LibraryNos  permite  extender  el  sistema  de  templates  de  Django  con  Filters  y  Tags  propiosUso{% load milibreria %}...{{ variable|mifiltro:"param" }}...{% mitag param1 param2 %}
    • Template  LibraryNos  permite  extender  el  sistema  de  templates  de  Django  con  Filters  y  Tags  propiosUso{% load milibreria %}...{{ variable|mifiltro:"param" }}...{% mitag param1 param2 %}Creación
    • 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.
    • 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 templateregister = template.Library()def cut(value, arg= ):return value.replace(arg, )register.filter(cut, cut)Ejemplo
    • 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 templateregister = template.Library()@register.filter(name=cut)def cut(value, arg= ):return value.replace(arg, )
    • Python  2.4  se  hizo  sexyCustom  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 templateregister = template.Library()@register.filter(name=cut)def cut(value, arg= ):return value.replace(arg, )
    • Nuestro  propio  Filter  en  dwiiera)Crear  un  Filter  llamado  |mention  que  al  detectar  un  “@usuario”  convierta  ese  texto  en  un  enlace  al  perfil  de  dwiier  de  ese  usuario.
    • Custom  TagsEl  método  genérico  para  crear  Tags  es  complejo.Vamos  a  ver  cómo  crear  los  2  Hpos  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
    • SimpleTagsEjemplo:  Devolver  la  hora  actual  formateada.{% current_time "%Y-%m-%d %I:%M %p" %}
    • SimpleTagsEjemplo:  Devolver  la  hora  actual  formateada.{% current_time "%Y-%m-%d %I:%M %p" %}from django import templateregister = template.Library()@register.simple_tagdef current_time(format):try:return datetime.datetime.now().strftime(str(format))except UnicodeEncodeError:return
    • InclusionTagsEjemplo:  Mostar  anuncios  si  el  usuario  no  es  premium.{% show_adverts user %}{% for advert in adverts %}<img src={{ advert.image }} />{% endfor %}adverts.htmlmilibreria.py
    • 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.htmlmilibreria.py
    • Nuestro  propio  TemplateTag  en  dwiiera)Crear  un  Tag  llamado  toggle_follow  que  permita  pintar  un  enlace  de  ‘follow’  o  ‘unfollow’  junto  a  cada  usuario  dwiier  que  aparece  listado  en  users_page.html
    • Ejercicios  para  subir  notac) Implementar  “retweet”:  un  botón  junto  a  cada  tweet  del  Hmeline  que  publique  el  mismo  tweet  en  tu  nombre  precedido  por  “RT  “.b)Implementar  “borrar  tweet”:  un  botón  junto  a  cada  tweet  propio  que  lo  elimine.a)Implementar  “página  de  menHons”:  un  Hmeline  que  sólo  muestre  los  tweets  que  te  mencionen  a  H  (Hp:  message__icontains=).
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • MiddlewareNos  permite  escribir  funcionalidad  reu*lizable  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,)
    • Middleware1. Sistema  de  BETA1. Nos  aseguramos  de  controlar  todas  páginas.2. Si  el  usuario  Hene  una  IP  o  un  User  o...2. Si@o  en  Mantenimiento1. Todo  el  Site  muestra  un  splash  excepto...3. Cache  Middleware1. Si  la  vista  cumple  un  patrón  (User  no  logeado,...)  cacheamos  la  página.4.  etc...
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Ofrece  integración  con  la  librería  GNU  ge@ext  de  i18n1. Un  fichero  .pot  conHene  todos  los  strings  usadoscontabilidad.pot2. En  cada  fichero  .po  se  guarda  una  traducciónes_ES.pot      es_AR.pot      en_GB.pot3. Cada  .po  se  compila  y  genera  un  .mo  binarioes_ES.mo      es_AR.mo      en_GB.moInternacionalización
    • Internacionalización• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?• GesHón  cómoda  de  singulares  y  plurales
    • Internacionalizaciónfrom django.utils.translation import ugettext as _print _("Cadena de texto")• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?• GesHón  cómoda  de  singulares  y  plurales
    • Internacionalizaciónfrom django.utils.translation import ugettext as _print _("Cadena de texto")• ¿Cómo  indicar  qué  strings  deben  ser  traducidos?from django.utils.translation import ungettextfrase = ungettext("Hay %(total)d resultado","Hay %(total)d resultados", total)% { total: total }• GesHón  cómoda  de  singulares  y  plurales
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • caching•Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache!•Recomendado  =  memcached•Acceder  a  la  BD  es  caro,  muy  caro.•El  Hardware  es  “gra*s”  en  comparación  con  op*mizar  código  op*mizado.•Ejemplo  (Facebook):
    • caching•Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache!•Recomendado  =  memcached•Acceder  a  la  BD  es  caro,  muy  caro.•El  Hardware  es  “gra*s”  en  comparación  con  op*mizar  código  op*mizado.•Ejemplo  (Facebook):300+Tb  Memcached
    • cachingfrom django.views.decorators.cache import cache_page@cache_page(60 * 15)def my_view(request):...views
    • cachingfrom django.views.decorators.cache import cache_page@cache_page(60 * 15)def my_view(request):...views{% load cache %}{% cache 500 sidebar %}.. sidebar ..{% endcache %}templates
    • cachinglow  level
    • cachinglow  level>>> from django.core.cache import cache>>> cache.set(my_key, hello, world!, 30)>>> cache.get(my_key)hello, world!•Podemos  cachear  cualquier  *po  de  objeto  que  se  pueda  serializar.•  QuerySets•  Listas•  ...
    • memcached  DEMO
    • ¿Cómo  haríais  un  ranking  de  puntuaciones?
    • ¿y  para  500k  Usuarios?
    • ¿y  para  2Millones?
    • ¿y  para  ++10Millones?
    • ¿y  para  ++10Millones?
    • redis
    • redis•  La  misma  filosoxa  de  memcached  pero  con  grandes  diferencias:•  Atómico•  Persistencia•  Tipos  “ricos”  (list,  sets,  sorted  sets,  etc..)•  Demo  :  Sistema  de  Ranking•  ¿Cómo  ges*onar  un  ranking  de  más  10Millones  de  usuarios?•  Cada  uuid  es  un  sha1()  -­‐>  40  caracteres.•  Las  Puntuaciones  son  random  entre  0  y  100.000  puntos.•  Los  datos  se  han  introducido  de  manera  aleatoria.
    • redis
    • redis•  Introducir  10Millones  de  elementos  en  redis:•  17minutos  -­‐>  1020segundos  -­‐>  ~  0,1  ms  por  insert.•  1.6gb  en  memoria  WTF!!•  int  =  4bytes  *  10M  =  40Millones  de  bytes  =  38Mb•  char(40)  =  40  bytes  *  10M  =  400Millones  de  bytes  =  381Mb•  419Mb  en  total  de  datos  ocupan  1.6gb  en  RAM
    • redis•  Introducir  10Millones  de  elementos  en  redis:•  17minutos  -­‐>  1020segundos  -­‐>  ~  0,1  ms  por  insert.•  1.6gb  en  memoria  WTF!!•  int  =  4bytes  *  10M  =  40Millones  de  bytes  =  38Mb•  char(40)  =  40  bytes  *  10M  =  400Millones  de  bytes  =  381Mb•  419Mb  en  total  de  datos  ocupan  1.6gb  en  RAM¡Más  que  aceptable  para  dar  solución  a  un  problema  con  10Millones  de  usuarios!
    • redis  DEMO
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Deploying  Django1. hip://virtualenv.openplans.org/2. hip://pip.openplans.org/
    • Deploying  DjangoVirtualenv  +  PIP  1. hip://virtualenv.openplans.org/2. hip://pip.openplans.org/
    • Virtualenv•Independencia  completa  de  las  librerías  del  sitema.•Cada  proyecto  *ene  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  *ene  su  juego  de  librerías  en  la  versión  que  necesita•Sin  miedo  a  actualizar•Sin  miedo  a  migrar•etc...$ virtualenv mi_entornocrear
    • Virtualenv•Independencia  completa  de  las  librerías  del  sitema.•Cada  proyecto  *ene  su  juego  de  librerías  en  la  versión  que  necesita•Sin  miedo  a  actualizar•Sin  miedo  a  migrar•etc...$ virtualenv mi_entornocrear$ source mi_entorno/bin/activateac/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.4.2psycopg2feedparser==4.1stripogram==1.5GChartWrapper==0.8pip install -E mi_entorno -r REQUIREMENTS
    • Nuestro  primer  Virtualenv  +  PIPa)Crear  un  entorno  virtualb)Instalar  Django==1.0c) Probar  django.VERSION
    • El  Stack
    • nginx  +  Gunicornnginxgunicorn•  nginx  [engine  x]  is  a  HTTP  and  reverse  proxy  server.•  Con  una  configuración  muy  sencilla  podremos  u*lizarlo  como  proxy  inverso  a  gunicorn.•  hGp://gunicorn.org/•  Servidor  Web  WSGI  implementado  en  Python•  Facilidades  de  puesta  en  marcha  de  proyectos  django•  Fácilmente  configurable  usando  nginx•  hGp://nginx.org/
    • nginx  :80gunicornDjangoWSGI  ServerFrontendDeploysencilloworker  1 worker  2 worker  n
    • gunicornDjangonginx  :80web1gunicornDjangonginx  :80web2gunicornDjangonginx  :80webnnginx  :80  :443varnishhaproxyfrontend1nginx  :80  :443varnishhaproxyfrontend2ipfailoverDeployno  tan  sencillo
    • Fabric
    • Repe**on  leads  to  boredom,boredom  to  horrifying  mistakes,horrifying  mistakes  to  God-­‐I-­‐wish-­‐I-­‐was-­‐s*ll-­‐bored.“
    • $ fab deploy -R test
    • $ fab deploy -R www
    • env.user = "example"env.hosts = ["web1.com", "web2.com", "..."]def deploy():run(git pull /home/site/)sudo(service supervisord restart)
    • Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
    • Apps
    • django-­‐south
    • django-­‐south•  Sistema  inteligente  para  realizar  de  manera  automá*ca  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  an*guo  Modelo  a  uno  nuevo...  south!•Necesito  que  ...  south!hGp://south.aeracode.org/
    • django-­‐south$ python manage.py schemamigration website --initialcrear  primer  schema$ python manage.py schemamigration website --autocrear  2-­‐*  migración$ python manage.py migrateaplicar  migraciones
    • django-­‐southhGp://south.aeracode.org/$ python manage.py schemamigration website --initialcrear  primer  schema$ python manage.py schemamigration website --autocrear  2-­‐*  migración$ python manage.py migrateaplicar  migraciones
    • django-­‐haystack  h@p://haystacksearch.org
    • django-­‐haystack•  “EL”  Sistema  de  búsquedas  para  Django•  Funciona  con  varios  sistemas  de  Indexación•  Solr,  Xapian,  Whoosh•  Features:•  ‘More  like  this’•Face*ng•Highligh*ng•  Spelling  Sugges*on•  etc...  h@p://haystacksearch.org
    • django-­‐registra/on  h@p://bitbucket.org/ubernostrum/django-­‐registra/on/
    • django-­‐registra/on•Sistema  completo  para  la  ges*ón  de  usuarios.•Desde  el  registro,  ac*vación  etc...•DRY!!•Instalación  muy  sencilla.  h@p://bitbucket.org/ubernostrum/django-­‐registra/on/
    • django-­‐registra/on  h@p://bitbucket.org/ubernostrum/django-­‐registra/on/
    • django-­‐registra/on/ac*vate/complete//ac*vate/<ac*va*on_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//  reac*vate/  h@p://bitbucket.org/ubernostrum/django-­‐registra/on/
    • django-­‐socialregistra/on  h@p://github.com/flashingpumpkin/django-­‐socialregistra/on
    • django-­‐socialregistra/on•Configuración  sencilla•Auten*cación  con:•twiGer,  facebook,  oauth,  openid•Integración  perfecta  con  contrib.auth  h@p://github.com/flashingpumpkin/django-­‐socialregistra/on
    • django-­‐debug-­‐toolbar  h@p://github.com/robhudson/django-­‐debug-­‐toolbar
    • Celery  h@p://celeryproject.org
    • •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
    • from celery.decorators import task@taskdef add(x, y):return x + y>>> result = add.delay(4, 4)>>> result.wait() # wait for and return the result8Celery  h@p://celeryproject.org
    • 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
    • dajaxproject.com
    • •  Set  de  liberías  AJAX  para  django.•  django-­‐dajaxice•  Core  de  comunicación.•  Enviar  información  asyncronamente.•  django-­‐dajax•  manipular  el  DOM  usando  Python.dajaxproject.com
    • Communica*on  uniforme  entre  el  cliente  y  el    servidor  .•  Agnos*co  a  cualquier  Framework  JS.•  Prototype,  jQuery,  etc...•  Lógica  de  presentación  fuera  de  las  vistas.•  Crossbrowsing.Obje/vos  dajaxice
    • Ejemplofrom django.utils import simplejsonfrom dajaxice.decorators import dajaxice_register@dajaxice_registerdef my_example(request):return simplejson.dumps({message:Hello World})
    • Ejemplofrom django.utils import simplejsonfrom dajaxice.decorators import dajaxice_register@dajaxice_registerdef my_example(request):return simplejson.dumps({message:Hello World})Si. es una funcionque retorna json.
    • Ejemplofunction on_whatever(){Dajaxice.example.my_example(my_js_callback);}
    • Ejemplofunction on_whatever(){Dajaxice.example.my_example(my_js_callback);}appfunction namecallback
    • Ejemplofunction my_js_callback(data){alert(data.message);}
    • Ejemplofunction my_js_callback(data){alert(data.message);}callbackyour stuff
    • •  Manipular  el  DOM  usando  Python.•  Sin  necesidad  de  conocer  JS  en  profundidad.•  Soporta  Frameworks  comoObje/vos  dajax
    • Ejemplofrom dajax.core.Dajax import Dajaxdef assign_test(request):dajax = Dajax()dajax.assign(#list li,innerHTML,Hello!)dajax.add_css_class(#list li,new)...return dajax.json()
    • Ejemplofrom dajax.core.Dajax import Dajaxdef assign_test(request):dajax = Dajax()dajax.assign(#list li,innerHTML,Hello!)dajax.add_css_class(#list li,new)...return dajax.json()tus acciones
    • Ejemplofunction on_whatever(){Dajaxice.app.assign_test(Dajax.process);}
    • Ejemplofunction on_whatever(){Dajaxice.app.assign_test(Dajax.process);}Dajaxcallback
    • DEMO
    • django-­‐tastypieh@p://django-­‐tastypie.readthedocs.org/
    • django-­‐tastypie•  Framework  para  crear  APIs  RESTful•  Muy  fácil  instalación•  Serialización  a:•JSON,  XML,  YAML  bplist  ...•OAuthh@p://django-­‐tastypie.readthedocs.org/
    • Sentry    -­‐  getsentry.com  h@p://getsentry.com
    • django-­‐command-­‐extensions  h@p://code.google.com/p/django-­‐command-­‐extensions/
    • django-­‐command-­‐extensions•Extensión  para  “manage.py”•Muchas  u*lidades  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.  h@p://code.google.com/p/django-­‐command-­‐extensions/
    • django-­‐command-­‐extensions
    • django-­‐command-­‐extensions
    • django-­‐command-­‐extensions
    • django-­‐command-­‐extensions
    • Alterna/vas  h@p://flask.pocoo.org  h@p://tornadoweb.org
    •  h@p://flask.pocoo.orgfrom flask import Flaskapp = Flask(__name__)@app.route("/")def hello():return "Hello World!"if __name__ == "__main__":app.run()$ pip install Flask$ python hello.py* Running on http://localhost:5000/
    • import tornado.ioloopimport tornado.webclass MainHandler(tornado.web.RequestHandler):def get(self):self.write("Hello, world")application = tornado.web.Application([(r"/", MainHandler),])if __name__ == "__main__":application.listen(8888)tornado.ioloop.IOLoop.instance().start()  h@p://tornadoweb.org•  real-­‐/me  •  non-­‐blocking  •  epoll
    • Sublime  Text  2  h@p://www.sublimetext.com/2
    • Pycharm  h@p://www.jetbrains.com/pycharm
    • La  punta  del  iceberg
    •  h@p://www.djangobook.com
    • How  to  ...  using  Django?