Desarrollo web ágil con Python y Django

10,449
-1

Published on

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

Published in: Technology
2 Comments
23 Likes
Statistics
Notes
No Downloads
Views
Total Views
10,449
On Slideshare
0
From Embeds
0
Number of Embeds
10
Actions
Shares
0
Downloads
692
Comments
2
Likes
23
Embeds 0
No embeds

No notes for slide

Desarrollo web ágil con Python y Django

  1. 1. Jorge  Bas*dame@jorgebas*da.com@jorgebas*daJaime  Irurzunjaime@irurzun.com@jaimeirurzun
  2. 2. Jorge  Bas*dame@jorgebas*da.com@jorgebas*daJaime  Irurzun  jaime@irurzun.com@jaimeirurzun
  3. 3. Evaluación
  4. 4. Í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
  5. 5. Í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
  6. 6. • 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,  ...
  7. 7. 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
  8. 8. El  Intérprete
  9. 9. El  Intérprete$ python holamundo.pyhola mundo!$Modo  Batch#!/usr/bin/env pythonprint "hola mundo!"holamundo.py
  10. 10. 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
  11. 11. Í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
  12. 12. Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject
  13. 13. Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35Llong
  14. 14. Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falsebool
  15. 15. Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str
  16. 16. Tipos  de  datos  h@p://docs.python.org/library/stdtypes.htmlobject1234 3.1415int float35LlongTrue Falseboolspam "guidos" """n lines"""str[1, [2, three], 4]list
  17. 17. 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
  18. 18. 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
  19. 19. 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!
  20. 20. Í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
  21. 21. Operadores  h@p://docs.python.org/library/operator.html
  22. 22. Operadoresnuméricosa + b a - b a * b a / ba % b -a +a a ** b  h@p://docs.python.org/library/operator.html
  23. 23. 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
  24. 24. 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
  25. 25. Í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
  26. 26. Usos  frecuentes:  list
  27. 27. Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1
  28. 28. Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1>>> 2 in numsTrue
  29. 29. Usos  frecuentes:  list>>> nums = [1, 2, 3]>>> nums[0]1>>> nums.append(4)>>> print nums[1, 2, 3, 4]>>> 2 in numsTrue
  30. 30. 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
  31. 31. Usos  frecuentes:  str
  32. 32. Usos  frecuentes:  str>>> "Python mola"[1:4]yth
  33. 33. Usos  frecuentes:  str>>> "Python mola"[1:4]yth>>> "Python mola".find("mola")7
  34. 34. Usos  frecuentes:  str>>> "Python mola"[1:4]yth>>> "Python mola".find("mola")7>>> "Python mola".replace("Python", "PHP no")PHP no mola
  35. 35. 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]
  36. 36. 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"
  37. 37. Usos  frecuentes:  dict
  38. 38. Usos  frecuentes:  dict>>> user = {nick: neo, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]
  39. 39. Usos  frecuentes:  dict>>> user = {nick: neo, phone: 5555}>>> user.keys()[nick, phone]>>> user.values()[neo, 5555]>>> user[nick]neo>>> user.get(age, 26)26
  40. 40. 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
  41. 41. 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}
  42. 42. Usos  frecuentes:  str  %
  43. 43. Usos  frecuentes:  str  %>>> "%s es muy sabio" % "Hycker"Hycker es muy sabio
  44. 44. Usos  frecuentes:  str  %>>> "%s es muy sabio" % "Hycker"Hycker es muy sabio>>> "%s sabe %i idiomas" % ("Hycker", 5)Hycker sabe 5 idiomas
  45. 45. 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
  46. 46. 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
  47. 47. 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
  48. 48. 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
  49. 49. Módulosjuego/__init__.pybonus/__init__.pyestrella.pymoneda.pyplanta.py...personajes/__init__.pymario.pyluigi.pyprincesa.py...enemigos/__init__.pyseta.pytortuga.pybomba.py...
  50. 50. 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()
  51. 51. Í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
  52. 52. {}Estructuras
  53. 53. {}Estructuras
  54. 54. >>> from __future__ import bracesFile "<stdin>", line 1SyntaxError: not a chanceIdentación4  Espac/os  para  la  identación
  55. 55. >>> from __future__ import bracesFile "<stdin>", line 1SyntaxError: not a chanceIdentación4  Espac/os  para  la  identaciónPEP 8
  56. 56. •  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/
  57. 57. def my_first_function(p1, p2):return "Hello World!"FuncionesMinúsculasPalabras  separadas  por  _Evitar  camelCase
  58. 58. def my_first_function(p1, p2):return "Hello World!"123FuncionesMinúsculasPalabras  separadas  por  _Evitar  camelCasePEP 8
  59. 59. Conversión  de  /pos  h@p://docs.python.org/library/func/ons.html
  60. 60. Conversión  de  /pos>>> int(1.3)1  h@p://docs.python.org/library/func/ons.html
  61. 61. Conversión  de  /pos>>> str(2)2>>> int(1.3)1  h@p://docs.python.org/library/func/ons.html
  62. 62. Conversión  de  /pos>>> str(2)2>>> int(1.3)1>>> float(1)1.0  h@p://docs.python.org/library/func/ons.html
  63. 63. 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
  64. 64. 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
  65. 65. Funciones  comunes  h@p://docs.python.org/library/func/ons.html
  66. 66. Funciones  comunes>>> len("Python Mola")11>>> len([1,2,3,4])4  h@p://docs.python.org/library/func/ons.html
  67. 67. 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
  68. 68. 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
  69. 69. 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
  70. 70. Funciones  interesantesSon  sólo  un  ejemplo...  h@p://docs.python.org/library/func/ons.html
  71. 71. 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
  72. 72. 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
  73. 73. 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
  74. 74. 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
  75. 75. Funciones  de  ayuda
  76. 76. 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]
  77. 77. 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)
  78. 78. 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
  79. 79. 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
  80. 80. El  operador  ()• Es  importante  diferenciar:funcion      vs      funcion()Clase              vs        Clase()• El  operador  ()  permite:• Invocar  funciones:• Instanciar  clases:resultado = funcion()objeto = Clase("param1")
  81. 81. Í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
  82. 82. $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
  83. 83. $count = 0;while ($count < 5) {echo "Number ".$count;$count+=1;}count = 0while count < 5:print "Number %i" % countcount+=1Sentencias:  while
  84. 84. for ($i=0; $i < 5; $i++) {echo "Number ".$count;}for i in range(4):print "Number %i" % countSentencias:  for
  85. 85. try {$result = 3 / 0;} catch (Exception $e) {echo "Division by Zero"}try:result = 3 / 0except:print "Division by Zero"Sentencias:  try-­‐except
  86. 86. Prueba  de  sentencias  en  consola
  87. 87. •  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
  88. 88. •  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
  89. 89. Ejemplo  PythonhGp://bit.ly/ejemplo-­‐python    
  90. 90. Ejercicio  PythonhGp://bit.ly/ejercicio-­‐python    
  91. 91. SolucioneshGp://bit.ly/ejercicio-­‐resueltohGp://bit.ly/ejercicio-­‐resuelto-­‐awesome
  92. 92. Í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
  93. 93. Evolución  de  la  WebDesarrollo  Web1ª  Generación 2ª  Generación 3ª  GeneraciónHTMLCGIPHPASPJSP...DjangoRailsSymfony...
  94. 94. Frameworks  web
  95. 95. Django:  Qué  y  dónde
  96. 96. •  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
  97. 97. •  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
  98. 98. •  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/
  99. 99. La  comunidad
  100. 100. La  comunidad• django-­‐users23.000  miembros• django-­‐developers7.400  miembros• djangoproject.com+500.000  visitas  únicas  mensuales
  101. 101. ¿Quién  usa  Django?
  102. 102. ¿Quién  usa  Django?
  103. 103. 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
  104. 104. 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
  105. 105. 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
  106. 106. •  Vamos  a  uHlizar  SQLite  por  comodidad•  Desde  Python  2.5  podemos  uHlizar  sqlite    sin  instalar  nada.2.  Instalación  SGBD
  107. 107. •  Vamos  a  uHlizar  SQLite  por  comodidad•  Desde  Python  2.5  podemos  uHlizar  sqlite    sin  instalar  nada.2.  Instalación  SGBD
  108. 108. 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
  109. 109. All  Right?
  110. 110. 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
  111. 111. Bienvenidos  al  mundo  de  Oz
  112. 112. *  Incluida  la  carpeta  del  proyectoFicheros  y  Carpetas¿Es  Django  tán  simple  y  fácil  de  usar?
  113. 113. *  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
  114. 114. Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
  115. 115. Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasFicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
  116. 116. Rails Symfony149 11735 29*  Incluida  la  carpeta  del  proyectoFicheros  y  CarpetasDjango52FicherosCarpetas¿Es  Django  tán  simple  y  fácil  de  usar?
  117. 117. Let’s  enjoy
  118. 118. Crear  nuestro  proyectode  5  ficheros  ;-­‐)
  119. 119. Crear  nuestro  proyecto$ django-admin.py startproject dwitterde  5  ficheros  ;-­‐)
  120. 120. 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  ;-­‐)
  121. 121. sesngs.py
  122. 122. Arrancar  nuestro  proyectode  5  ficheros  ;-­‐)
  123. 123. 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.
  124. 124. 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.
  125. 125. Í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
  126. 126. MVC  en  DjangoModelo  =  Model Vista  =  Template Controlador  =  URL+View
  127. 127. 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?
  128. 128. 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()
  129. 129. 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
  130. 130. 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
  131. 131. 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
  132. 132. ¡Recuerda!:  MVC
  133. 133. Í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
  134. 134. Templates• Separan  la  lógica  de  presentación  a  una  capa  independiente.• Ficheros  independientes  (.html)• Lenguaje  independiente  (¡para  diseñadores!)
  135. 135. 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."
  136. 136. 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
  137. 137. 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)
  138. 138. 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)
  139. 139. 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!
  140. 140. 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
  141. 141. 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)
  142. 142. 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...
  143. 143. 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})
  144. 144. 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...?
  145. 145. 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!
  146. 146. Templates:  TipTEMPLATE_DIRS = (/home/django/templates,)senngs.pya)
  147. 147. Templates:  TipTEMPLATE_DIRS = (/home/django/templates,)senngs.py Reusable  apps?a)
  148. 148. 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:
  149. 149. ¡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)
  150. 150. h@p://github.com/enjoydjango/dwi@er
  151. 151. Git
  152. 152. GitQuiero  ir  a...¿Donde  estoy?1ª
  153. 153. 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ª
  154. 154. GitIgnorar  todos  los  cambios  **  Si  no  habéis  commiteado  nada
  155. 155. Git$ git reset --hard HEAD$ git clean -fdIgnorar  todos  los  cambios  **  Si  no  habéis  commiteado  nada
  156. 156. h@p://github.com/enjoydjango/dwi@er
  157. 157. 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
  158. 158. 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
  159. 159. 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.
  160. 160. Templates:  {{}}<html><head>Ejemplo templates</head><body>Hola, {{ username }}.</body></html>{username: juan}<html><head>Ejemplo templates</head><body>Hola, juan.</body></html>
  161. 161. Filters  y  Tags
  162. 162. Filters  y  Tags
  163. 163. Filters  y  Tags{{ varible|filter }}filter
  164. 164. Filters  y  Tags{{ varible|filter }}filter{% tag var1 var2 %}inline  tag
  165. 165. Filters  y  Tags{{ varible|filter }}filter{% tag var1 var2 %}inline  tag{% tag var1 %}...{% endtag %}block  tag
  166. 166. Templates:  tags  {%  %}
  167. 167. Templates:  tags  {%  %}{% comment %} Bu! {% endcomment %}comment
  168. 168. Templates:  tags  {%  %}{% comment %} Bu! {% endcomment %}commentfor {% for elemento in lista %}<li>{{ elemento }}<li>{% endfor %}
  169. 169. 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
  170. 170. Templates:  tags  {%  %}
  171. 171. Templates:  tags  {%  %}cycle {% for elemento in lista %}<li class="{% cycle rojo azul %}">{{ elemento }}<li>{% endfor %}
  172. 172. Templates:  tags  {%  %}cycle {% for elemento in lista %}<li class="{% cycle rojo azul %}">{{ elemento }}<li>{% endfor %}include {% include "foo/bar.html" %}
  173. 173. 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 %}
  174. 174. 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 %}
  175. 175.  Tarea:  Tagsa) UHlizar  tags  para  que  el  Hmeline  se  muestre  con  el  siguiente  formato:• <username>:  <tweet>  <Hmestamp>• <username>:  <tweet>  <Hmestamp>• ...
  176. 176.  Tarea:  Tags  avanzadosa) Hacer  que  el  Hmeline  muestre  el  mensaje  “No  hay  tweets.”  si  el  diccionario  recibido  está  vacío.
  177. 177. 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
  178. 178. Templates:  Filters
  179. 179. Templates:  Filters{username: Juan es majo}{{ username|length }}length 12
  180. 180. Templates:  Filters{username: Juan es majo}{{ username|length }}length 12{{ username|cut }}cut Juanesmajo
  181. 181. Templates:  Filters{username: Juan es majo}{{ username|length }}length 12{{ username|cut }}cut Juanesmajo{{ username|slugify }}slugify juan-es-majo
  182. 182. Templates:  Filters{username: Juan es majo}{{ username|length }}length 12{{ username|cut }}cut Juanesmajo{{ username|slugify }}slugify juan-es-majo{{ username|wordcount }}wordcount 3
  183. 183. 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
  184. 184. 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
  185. 185. Templates:  Filters
  186. 186. Templates:  Filters{username: Juan es <b>majo, guapo y <em>listo</em></b>}{{ username|striptags }}striptagsJuan es majo guapo y listo
  187. 187. 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> ...
  188. 188. 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>
  189. 189. Templates:  Filters
  190. 190. Templates:  Filters{url: Visitad http://www.djangoproject.com}{{ url|urlize }}urlizeVisitad <a href=”http://www.djangoproject.com”> http://www.djangoproject.com </a>
  191. 191. 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>
  192. 192. Templates:  Filters{lista: [States, [Kansas, [Lawrence, Topeka], Illinois]]}
  193. 193. 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>
  194. 194. Templates:  Filters
  195. 195. Templates:  Filters{value: 123456789}{{ value|add:”1” }}add 123456790
  196. 196. Templates:  Filters{value: 123456789}{{ value|add:”1” }}add 123456790{{ value|filesizeformat }}filesizeformat 117.7MB
  197. 197. 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
  198. 198. 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
  199. 199. 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
  200. 200. Tarea:  Filtersa) Añadir  a  cada  tweet  del  Hmeline  el  Hempo  transcurrido:• <username>:  <tweet><n>  seconds  ago• <username>:  <tweet><n>  minutes  ago• ...
  201. 201. 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”  
  202. 202. Tarea:  Filtersc) Conseguir  que  todas  las  urls  que  aparezcan  en  los  tweets  se  conviertan  en  enlaces  <a  href=...  />  de  HTML.
  203. 203. 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 %}
  204. 204. 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
  205. 205. Í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
  206. 206. Modelos
  207. 207. ¿SQL?
  208. 208. 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})
  209. 209. 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
  210. 210. 12  lineas  de  Python...  ¬_¬
  211. 211. ORM  (Object-­‐RelaHonal  mapping)
  212. 212. ORM  (Object-­‐RelaHonal  mapping)
  213. 213. Ejemplo  ORMdef book_list(request):names = Books.objects.all().order_by(name)return render(request, book_list.html, {names:names})
  214. 214. Ejemplo  ORMdef book_list(request):names = Books.objects.all().order_by(name)return render(request, book_list.html, {names:names})1 2
  215. 215. Fucking  Ninjas!
  216. 216. 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)  
  217. 217. 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)  
  218. 218. Fucking  Awesome  Ninjas!
  219. 219. 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
  220. 220. 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
  221. 221. 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
  222. 222. 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
  223. 223. ¿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;
  224. 224. ¿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;
  225. 225. ¿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
  226. 226. Configurar  seyngs.pyDATABASES = {default: {ENGINE: django.db.backends.,NAME: ,USER: ,PASSWORD: ,HOST: ,PORT: ,}}postgresql_psycopg2,postgresql, mysql,sqlite3 or oracle.
  227. 227. Configurar  seyngs.pyDATABASES = {default: {ENGINE: django.db.backends.,NAME: ,USER: ,PASSWORD: ,HOST: ,PORT: ,}}123postgresql_psycopg2,postgresql, mysql,sqlite3 or oracle.
  228. 228. 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
  229. 229. 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
  230. 230. Nuestro  primer  modeloa)Crear  modelo  Tweetb)Configurar  sesngs.pyc) Ver  el  SQL  generado  con  sqlall
  231. 231. 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
  232. 232. 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
  233. 233. ¿Cuantos  sistemas  de  AutenHcación  habéis  programado?
  234. 234. ¿Alguno  era  mejor  que  el  anterior?  ;-­‐)
  235. 235. contrib.auth  puede  ser  el  úlHmo  :D
  236. 236. 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
  237. 237. 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
  238. 238. BD  Lista  para  usarse
  239. 239. BD  Lista  para  usarse
  240. 240. Nuestro  primer  modeloa)Hacer  syncdb
  241. 241. Previo:  Clases  del  ORMts = Publisher.objects.all()ModelManagerQuerySet
  242. 242. INSERT
  243. 243. 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()
  244. 244. 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)
  245. 245. UPDATE
  246. 246. UPDATE>>> ...>>> p.id52>>> p.name = Apress Publishing>>> p.save()o.save()1
  247. 247. UPDATE>>> Publisher.objects.all().update(country=USA)2>>> ...>>> p.id52>>> p.name = Apress Publishing>>> p.save()o.save()queryset.update(...)1n
  248. 248. DELETE
  249. 249. DELETE>>> ...>>> p.id52>>> p.delete()o.delete()1
  250. 250. DELETE>>> ps = Publisher.objects.all()>>> ps.delete()>>> ...>>> p.id52>>> p.delete()o.delete()queryset.delete()1n
  251. 251. SELECT  de  1  resultado
  252. 252. SELECT  de  1  resultado>>> Publisher.objects.get(name="Apress")<Publisher: Apress>.get(...)
  253. 253. 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.
  254. 254. 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.
  255. 255. SELECT  de  N  resultados
  256. 256. SELECT  de  N  resultados>>> Publisher.objects.all()[<Publisher: Apress>, <Publisher: OReilly>].all()
  257. 257. 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(...)
  258. 258. 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(...)
  259. 259. 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!
  260. 260. get(),  filter()  y  exclude()
  261. 261. get(),  filter()  y  exclude()Modelo.objects.filter(campo1="valor1", campo2="valor2")Los  parámetros  pueden  indicar  mucho  más  que  igualdad  (=)
  262. 262. 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
  263. 263. ORDER  BY
  264. 264. ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)
  265. 265. ORDER  BY>>> Publisher.objects.order_by("name")[<Publisher: Apress>, <Publisher: OReilly>].order_by(...)>>> Publisher.objects.order_by("-name")[<Publisher: OReilly>, <Publisher: Apress>]
  266. 266. 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:
  267. 267. 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!
  268. 268. Slicing
  269. 269. 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>]
  270. 270. 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
  271. 271. 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
  272. 272. Related  Objects
  273. 273. Related  ObjectsOneToOneFieldclass Coche(models.Model):motor = OneToOneField(Motor)class Motor(models.Model):...11
  274. 274. 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
  275. 275. 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
  276. 276. Related  Objects
  277. 277. Related  ObjectsForeignKeyFieldclass Blog(models.Model):...class Post(models.Model):blog = ForeignKeyField(Blog)1n
  278. 278. 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
  279. 279. Related  Objects
  280. 280. Related  ObjectsManyToManyFieldclass Post(models.Model):tags = ManyToManyField(Tag)class Tag(models.Model):...nm
  281. 281. 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
  282. 282. Related  Objects
  283. 283. Related  ObjectsEn  todas  ellas  podemos  renombrar  el  puntero  inversoclass Blog(models.Model):...class Post(models.Model):blog = ForeignKeyField(Blog, related_name=posts)1n
  284. 284. 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
  285. 285. 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
  286. 286. Y  la  guinda  final:  ¡Todo  es  LAZY!
  287. 287. Laziness
  288. 288. 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):
  289. 289. Nota:  __unicode__()
  290. 290. Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
  291. 291. Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
  292. 292. Nota:  __unicode__()>>> Publisher.objects.all()[<Publisher: Publisher object>]
  293. 293. Nota:  __unicode__()class Publisher(models.Model):...def __unicode__(self):return self.name>>> Publisher.objects.all()[<Publisher: Publisher object>]
  294. 294. Nota:  __unicode__()class Publisher(models.Model):...def __unicode__(self):return self.name>>> Publisher.objects.all()[<Publisher: Publisher object>]>>> Publisher.objects.all()[<Publisher: Apress>]
  295. 295. Usando  el  ORMa)Insertar  varios  Tweets  desde  la  shell.b)Modificar  views.timeline  para  que  uHlice  los  Tweets  reales  de  la  BD.
  296. 296. 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
  297. 297. Profiles
  298. 298. 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.
  299. 299. Profilemodels.py
  300. 300. 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.
  301. 301. Profile•Donde  tengamos  el  User  tendremos  el  Profile.•Donde  tengamos  el  Profile,  tendremos  el  User.
  302. 302. 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.
  303. 303. 1  User  =  1  Profile  ¿Cuándo  se  crea  un  User?
  304. 304. 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/
  305. 305. Signals
  306. 306. 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
  307. 307. 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
  308. 308. Followers
  309. 309. Profilemodels.py
  310. 310. 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
  311. 311. Users  en  dwiiera)Añadir  ManyToMany  para  los  followers.b)Eliminar  BD.c) Hacer  syncdb
  312. 312. 1,2,3  Borrar  la  BD....  1,2,3...  Borrar  la  BD
  313. 313. Í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
  314. 314. CRUD:  Create,  Retrieve,  Update  &  Delete
  315. 315. django.contrib.admin123
  316. 316. django.contrib.admin123
  317. 317. django.contrib.admin1
  318. 318. 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
  319. 319. 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
  320. 320. Django  admin:  InstalaciónINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,...)senngs.py
  321. 321. Django  admin:  InstalaciónINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,django.contrib.admin,...)senngs.py1
  322. 322. Actualizando  la  BD
  323. 323. Actualizando  la  BD$ python manage.py syncdbCreating table django_admin_logInstalling index for admin.LogEntry modelAdmin  lista  para  usar
  324. 324. ¿Y  nuestra  app??
  325. 325. ¿Y  nuestra  app?
  326. 326. 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)
  327. 327. Instalar  Admina)Configurar  urls.pyb)Configurar  sesngs.pyc) Hacer  syncdb
  328. 328. Instalar  Admind)Comprobar  que  no  están  Tweet  y  Profilee)Añadir  admin.pyf) Probar  Administración.
  329. 329. Fixtures
  330. 330. 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:
  331. 331. 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 ...>
  332. 332. 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.
  333. 333. 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
  334. 334. Í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
  335. 335. Formularios
  336. 336. Clases  involucradas
  337. 337. Clases  involucradasWidget Componente  visual  equivalente  a  HTMLTextInputCheckboxInput<input type=text...><input type=checkbox...>
  338. 338. 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, ...
  339. 339. 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, ...]
  340. 340. Fields
  341. 341. 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
  342. 342. 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
  343. 343. 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
  344. 344. 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
  345. 345. 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
  346. 346. 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
  347. 347. 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
  348. 348. 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
  349. 349. 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>:
  350. 350. 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>:
  351. 351. 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:
  352. 352. Forms  a  parHr  de  Models:  El  COLMO  del  DRY
  353. 353. 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
  354. 354. 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).
  355. 355. 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
  356. 356. Í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
  357. 357. Magia  avanzada
  358. 358. Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
  359. 359. Magia  avanzada1. Views  avanzadas2. Context  Processors3. Custom  Template  Filters  &  Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps  recomendadas
  360. 360. 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
  361. 361. 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!

×