1. Desarrollo web ágil con Python y DjangoJorge Bas7da PérezJaime Irurzun Graña
[email protected]@gmail.com @jorgebas7da @jaimeirurzun 2. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 3. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 4. • LegibleSintaxis intuiHva y estricta• Produc/voEntre 1/3 y 1/5 más conciso que Java o C++• Portable GNU/Linux, Windows, Mac OS X, ...• ExtensoStandard Library, Third parHes• Integrable C, C++, Java, .NET, COM, WS, CORBA, ...• ... y Diver/do 5. Instalación $ sudo apt-get install pythonhttp://www.python.org/download/Snow Leopard incluye las versiones 2.5.4 y 2.6.1 6. El Intérprete 7. El IntérpreteModo Batchholamundo.py$ python holamundo.py#!/usr/bin/env python hola mundo!print "hola mundo!" $ 8. El Intérprete Modo Batch holamundo.py$ python holamundo.py#!/usr/bin/env python hola mundo!print "hola mundo!" $ Modo Interac7vo$ 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! 9. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 10. Tipos de datosobject + info: hMp://docs.python.org/library/stdtypes.html 11. Tipos de datosint 1234 long 35Lfloat3.1415object + info: hMp://docs.python.org/library/stdtypes.html 12. Tipos de datosint 1234 long 35Lfloat3.1415 bool True Falseobject + info: hMp://docs.python.org/library/stdtypes.html 13. Tipos de datosint 1234 long 35Lfloat3.1415 bool True Falsestr spam"guidos""""n lines"""object + info: hMp://docs.python.org/library/stdtypes.html 14. Tipos de datosint 1234 long 35Lfloat3.1415 bool True Falsestr spam"guidos""""n lines"""objectlist[1, [2, three], 4] + info: hMp://docs.python.org/library/stdtypes.html 15. Tipos de datosint 1234 long 35Lfloat3.1415 bool True Falsestr spam"guidos""""n lines"""objectlist[1, [2, three], 4] dict {food: spam, taste: yum} + info: hMp://docs.python.org/library/stdtypes.html 16. Tipos de datos int 1234 long 35Lfloat3.1415 boolTrue False str spam"guidos""""n lines"""object list[1, [2, three], 4]dict {food: spam, taste: yum} tuple (1, spam, 4, U)+ info: hMp://docs.python.org/library/stdtypes.html 17. Tipos de datoso ¡T i p ad mi co! int 1234 long 35Lfloat d iná3.1415 boolTrue False str spam"guidos""""n lines"""object list[1, [2, three], 4]dict {food: spam, taste: yum} tuple (1, spam, 4, U)+ info: hMp://docs.python.org/library/stdtypes.html 18. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 19. Operadores+ info: hMp://docs.python.org/library/operator.html 20. Operadoresa + b a - ba * b a / bnuméricosa % b-a+aa ** b + info: hMp://docs.python.org/library/operator.html 21. Operadoresa + b a - ba * b a / bnuméricosa % b-a+aa ** b a < ba bcomparadores a >= b a == b a != b + info: hMp://docs.python.org/library/operator.html 22. Operadoresa + b a - ba * ba / bnuméricosa % b-a+a a ** b a < ba bcomparadores a >= b a == b a != b lógicosa or b a and bnot a + info: hMp://docs.python.org/library/operator.html 23. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 24. Usos frecuentes: list 25. Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1 26. Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1>>> 2 in numsTrue 27. Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1>>> 2 in numsTrue>>> nums.append(4)>>> print nums[1, 2, 3, 4] 28. Usos frecuentes: list>>> nums = [1, 2, 3]>>> nums[0]1>>> 2 in numsTrue>>> nums.append(4)>>> print nums[1, 2, 3, 4]>>> len(nums)4 29. Usos frecuentes: str 30. Usos frecuentes: str>>> "Python mola"[1:4]yth 31. Usos frecuentes: str>>> "Python mola"[1:4]yth>>> "Python mola".find("mola")7 32. Usos frecuentes: str>>> "Python mola"[1:4]yth>>> "Python mola".find("mola")7>>> "Python mola".replace("Python", "PHP no")PHP no mola 33. 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] 34. 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" 35. Usos frecuentes: dict 36. Usos frecuentes: dict>>> user = {nick: neo, age: 24}>>> user.keys()[nick, age]>>> user.values()[neo, 24] 37. Usos frecuentes: dict>>> user = {nick: neo, age: 24}>>> user.keys()[nick, age]>>> user.values()[neo, 24]>>> user[age] >>> user.get(age, 20)2424 38. Usos frecuentes: dict>>> user = {nick: neo, age: 24}>>> user.keys()[nick, age]>>> user.values()[neo, 24]>>> user[age] >>> user.get(age, 20)2424>>> user.has_key(nick)True 39. Usos frecuentes: dict>>> user = {nick: neo, age: 24}>>> user.keys()[nick, age]>>> user.values()[neo, 24]>>> user[age] >>> user.get(age, 20)2424>>> user.has_key(nick)True>>> user.update({nick: alatar, age: 25})>>> user{nick: alatar, age: 25} 40. Usos frecuentes: str % 41. Usos frecuentes: str %>>> "%s es muy sabio" % "Hycker"Hycker es muy sabio 42. Usos frecuentes: str %>>> "%s es muy sabio" % "Hycker"Hycker es muy sabio>>> "%s sabe %i idiomas" % ("Hycker", 5)Hycker sabe 5 idiomas 43. 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 44. Módulossound/__init__.py1. Un módulo es un fichero .pyformats/__init__.pywavread.pywavwrite.py2. Los módulos pueden aiffread.pyaiffwrite.pyauread.py organizarse en paquetes.auwrite.py...effects/__init__.py3. Un paquete es una carpeta echo.pysurround.pyreverse.pyque conHene un fichero con ...filters/__init__.py nombre __init__.pyequalizer.pyvocoder.pykaraoke.py... 45. Módulossound/ 2__init__.py 1. Un módulo es un fichero .pyformats/__init__.pywavread.pywavwrite.py 2. Los módulos pueden 1 aiffread.pyaiffwrite.pyauread.pyorganizarse en paquetes.auwrite.py...effects/__init__.py 3 3. Un paquete es una carpeta echo.pysurround.pyreverse.py que conHene un fichero con ...filters/__init__.pynombre __init__.pyequalizer.pyvocoder.pykaraoke.py... 46. Módulos import math ¿Dónde los busca Python?En la lista de directorios que conHene la lista sys.path: 1. El directorio actual:./ 2. El directorio site-packages de nuestro Python:/usr/local/lib/python2.6/site-packages 3. Los directorios apuntados por PYTHONPATH:$ env | grep PYTHONPATH 4. El directorio de la instalación de Python:/usr/lib/python2.6/ 47. Módulossound/ import sound.effects.echo__init__.pysound.effects.echo.echofilter(...)formats/__init__.pywavread.pywavwrite.pyaiffread.pyaiffwrite.pyauread.pyauwrite.py...effects/__init__.pyecho.pysurround.pyreverse.py...filters/__init__.pyequalizer.pyvocoder.pykaraoke.py... 48. Módulossound/ import sound.effects.echo__init__.pysound.effects.echo.echofilter(...)formats/__init__.pywavread.pywavwrite.pyfrom sound.effects import echoaiffread.pyecho.echofilter(...)aiffwrite.pyauread.pyauwrite.py...effects/__init__.pyecho.pysurround.pyreverse.py...filters/__init__.pyequalizer.pyvocoder.pykaraoke.py... 49. Módulossound/ import sound.effects.echo__init__.pysound.effects.echo.echofilter(...)formats/__init__.pywavread.pywavwrite.pyfrom sound.effects import echoaiffread.pyecho.echofilter(...)aiffwrite.pyauread.pyauwrite.py... from sound.effects.echo import echofiltereffects/ echofilter(...)__init__.pyecho.pysurround.pyreverse.py...filters/__init__.pyequalizer.pyvocoder.pykaraoke.py... 50. Módulossound/ import sound.effects.echo__init__.pysound.effects.echo.echofilter(...)formats/__init__.pywavread.pywavwrite.pyfrom sound.effects import echoaiffread.pyecho.echofilter(...)aiffwrite.pyauread.pyauwrite.py... from sound.effects.echo import echofiltereffects/ echofilter(...)__init__.pyecho.pysurround.pyreverse.py...from sound.effects.echo import *filters/ echofilter(...)__init__.pyequalizer.pyvocoder.pykaraoke.py... 51. Módulossound/ import sound.effects.echo__init__.pysound.effects.echo.echofilter(...)formats/__init__.pywavread.pywavwrite.pyfrom sound.effects import echoaiffread.pyecho.echofilter(...)aiffwrite.pyauread.pyauwrite.py... from sound.effects.echo import echofiltereffects/ echofilter(...)__init__.pyecho.pysurround.pyreverse.py...from sound.effects.echo import *filters/ echofilter(...)__init__.pyequalizer.pyvocoder.pykaraoke.py from sound.effects import echo as rev...rev.echofilter(...) 52. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 53. Estructuras {} 54. Estructuras {} 55. Identación>>> from __future__ import braces File "", line 1 SyntaxError: not a chance 56. Identación>>> from __future__ import braces File "", line 1 SyntaxError: not a chancePEP 8 4 Espacios para indicar la identación 57. ¿PEP 8? PEP 8• Guido van Rossum (2001)• Recomendaciones de esHlo• “Readability counts”• “Code is read much more ofen than it is wrigen.”• Muy recomendable importante seguirlo. hMp://www.python.org/dev/peps/pep-‐0008/ 58. Funcionesdef my_first_function(p1, p2):return "Hello World!" 59. Funciones1 def my_first_function(p1, p2):return "Hello World!" 60. Funciones21 def my_first_function(p1, p2):return "Hello World!" 61. Funciones21 def my_first_function(p1, p2):3 return "Hello World!" 62. Funciones 21 def my_first_function(p1, p2):3 return "Hello World!" PEP 8 Recomendaciones:• Minúsculas• Palabras separadas por _• Evitar camelCase 63. Conversión de /pos +info: hMp://docs.python.org/library/func7ons.html 64. Conversión de /pos>>> int(1.3)1 +info: hMp://docs.python.org/library/func7ons.html 65. Conversión de /pos>>> int(1.3)1>>> str(2)2 +info: hMp://docs.python.org/library/func7ons.html 66. Conversión de /pos>>> int(1.3)1>>> str(2)2>>> float(1)1.0 +info: hMp://docs.python.org/library/func7ons.html 67. Conversión de /pos>>> int(1.3)1 >>> tuple([1,2,3]) (1, 2, 3)>>> str(2)2>>> float(1)1.0 +info: hMp://docs.python.org/library/func7ons.html 68. Conversión de /pos>>> int(1.3)1 >>> tuple([1,2,3]) (1, 2, 3)>>> str(2)2 >>> list((1,2,3)) [1, 2, 3]>>> float(1)1.0 +info: hMp://docs.python.org/library/func7ons.html 69. Funciones comunes +info: hMp://docs.python.org/library/func7ons.html 70. Funciones comunes>>> len("Python Mola")11>>> len([1,2,3,4])4+info: hMp://docs.python.org/library/func7ons.html 71. Funciones comunes>>> len("Python Mola")11>>> len([1,2,3,4])4>>> range(5)[0, 1, 2, 3, 4]>>> range(1,7)[1, 2, 3, 4, 5, 6]>>> range(1,7,2)[1, 3, 5] +info: hMp://docs.python.org/library/func7ons.html 72. Funciones comunes >>> type(True)>>> len("Python Mola") 11 >>> type("Python Mola")>>> len([1,2,3,4]) 4>>> range(5)[0, 1, 2, 3, 4]>>> range(1,7)[1, 2, 3, 4, 5, 6]>>> range(1,7,2)[1, 3, 5] +info: hMp://docs.python.org/library/func7ons.html 73. Funciones comunes >>> type(True)>>> len("Python Mola") 11 >>> type("Python Mola")>>> len([1,2,3,4]) 4>>> range(5) >>> sum([0,1,2,3,4])[0, 1, 2, 3, 4]10>>> range(1,7) >>> sum(range(5))[1, 2, 3, 4, 5, 6] 10>>> range(1,7,2)[1, 3, 5] Y un muy largo etc... +info: hMp://docs.python.org/library/func7ons.html 74. Funciones interesantes Son sólo un ejemplo...+info: hMp://docs.python.org/library/func7ons.html 75. Funciones interesantes>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]Son sólo un ejemplo... +info: hMp://docs.python.org/library/func7ons.html 76. Funciones interesantes>>> a = [1,2,3]>>> b = [4,5,6]>>> zip(a,b)[(1, 4), (2, 5), (3, 6)]>>> sorted([5,1,3,4,2])[1, 2, 3, 4, 5]Son sólo un ejemplo... +info: hMp://docs.python.org/library/func7ons.html 77. Funciones interesantes>>> a = [1,2,3]>>> b = [4,5,6]>>> round(1.2345,2)>>> zip(a,b) 1.23[(1, 4), (2, 5), (3, 6)]>>> sorted([5,1,3,4,2])[1, 2, 3, 4, 5]Son sólo un ejemplo... +info: hMp://docs.python.org/library/func7ons.html 78. Funciones interesantes>>> a = [1,2,3]>>> b = [4,5,6]>>> round(1.2345,2)>>> zip(a,b) 1.23[(1, 4), (2, 5), (3, 6)]>>> sorted([5,1,3,4,2]) >>> map(str,[1,2,3,4,5])[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]Son sólo un ejemplo... +info: hMp://docs.python.org/library/func7ons.html 79. Funciones de ayuda 80. 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] 81. 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) 82. Clasesclass Student(object):def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.name s = Student("Jorge", 24) 83. Clases1class Student(object):def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.name s = Student("Jorge", 24) 84. Clases12class Student(object):def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.name s = Student("Jorge", 24) 85. Clases12class Student(object):3 def __init__(self, name, age):self.name = nameself.age = agedef hello(self):return My name is %s % self.name s = Student("Jorge", 24) 86. Clases12class Student(object):3 def __init__(self, name, age):4 self.name = nameself.age = agedef hello(self):return My name is %s % self.name s = Student("Jorge", 24) 87. Clases12class Student(object):3 def __init__(self, name, age):4 self.name = nameself.age = agedef hello(self): 5return My name is %s % self.name s = Student("Jorge", 24) 88. Clases12class Student(object):3 def __init__(self, name, age):4 self.name = nameself.age = agedef hello(self): 5return My name is %s % self.name s = Student("Jorge", 24) PEP 8Recomendaciones: • CamelCase 89. El operador ()• Es importante diferenciar:funcion vs funcion()Clase vs Clase()• El operador () permite:• Invocar funciones:resultado = funcion()• Instanciar clases:objeto = Clase("param1") 90. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 91. Sentencias: if-‐else$name = "Jon"; name = "Jon"if($name == "Jon"){if name == "Jon":$name = "Jon Rocks!";name = "Jon Rocks!"}elif name == "Mary":elseif($name == "Mary"){ name = "Hello Mary"$name = "Hello Mary";else:}name = "Who are you?"else{$name = "Who are you?"} 92. Sentencias: while $count = 0; while ($count < 5) { echo "Number ".$count; $count+=1; } count = 0 while count < 5: print "Number %i" % count count+=1 93. Sentencias: forfor ($i=0; $i < 5; $i++) {echo "Number ".$count;}for i in range(4):print "Number %i" % count 94. Sentencias: try-‐except try { $result = 3 / 0; } catch (Exception $e) { echo "Division by Zero" } try: result = 3 / 0 except:print "Division by Zero" 95. Prueba de sentencias en consola 96. 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. 97. 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... 98. Ejemplo & Ejercicio 99. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 100. Evolución de la Web Desarrollo Web1ª Generación2ª Generación 3ª GeneraciónHTMLPHP Django CGIASPRailsJSPSymfony ...... 101. Frameworks web 102. Django: Qué y dónde 103. FilosoXa• Loose coupling, Acoplamiento débil.• Cada capa es independiente y desconoce completamente a las demás.• Menos código.• Rápido desarrollo.• Esto es el siglo 21, todo el trabajo tedioso hay que evitarlo.• Don’t Repeat Yourself (DRY) 104. FilosoXa• Loose coupling, Acoplamiento débil.• Cada capa es independiente y desconoce completamente a las demás.• Menos código.• Rápido desarrollo.• Esto es el siglo 21, todo el trabajo tedioso hay que evitarlo.• Don’t Repeat Yourself (DRY)“ Every distinct concept and/or piece of data should live in one, and only one, place. Redundancy is bad. Normalization is good.” 105. FilosoXa• Explicit is beger 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.hMp://docs.djangoproject.com/en/dev/misc/design-‐philosophies/ 106. La comunidad 107. La comunidad• django-‐users18.000 miembros 108. La comunidad• django-‐users18.000 miembros• django-‐developers5.900 miembros 109. La comunidad• django-‐users18.000 miembros• django-‐developers5.900 miembros• djangoproject.com500.000 visitas únicas mensuales 110. ¿Quién usa Django? 111. ¿Quién usa Django? etc... 112. 1. Instalación Python $ sudo apt-get install python http://www.python.org/download/Snow Leopard incluye las versiones 2.5.4 y 2.6.1 113. 2. Instalación SGBDConfigurar un motor de Base de Datos:• Oficiales: • Comunidad: • PostgreSQL• Sybase SQL Anywhere• MySQL • IBM DB2 • Microsof SQL Server 2005• Oracle • Firebird• SQLite• ODBC 114. 2. Instalación SGBDConfigurar un motor de Base de Datos:• Oficiales: • Comunidad: • PostgreSQL• Sybase SQL Anywhere• MySQL • IBM DB2 • Microsof SQL Server 2005• Oracle • Firebird• SQLite• ODBC 115. 2. Instalación SGBD• Vamos a uHlizar SQLite por comodidad• Desde Python 2.5 podemos uHlizar sqlite sin instalar nada. 116. 2. Instalación SGBD• Vamos a uHlizar SQLite por comodidad• Desde Python 2.5 podemos uHlizar sqlite sin instalar nada. 117. 3. Instalación DjangoA: Paquetes de cada distro • apt-get install python-djangoB: Official Release • hMp://www.djangoproject.com/download/ • python setup.py installC: Trunk • hMp://code.djangoproject.com/svn/django/trunk/ 118. All Right? 119. All Right?>>> import django>>> django.VERSION(1, 2, 3, final, 0)>>> import djangoTraceback (most recent call last):File "", line 1, in ImportError: No module named django 120. Bienvenidos al mundo de Oz 121. Ficheros y Carpetas¿Es Django tán simple y fácil de usar? * Incluida la carpeta del proyecto 122. Ficheros y Carpetas ¿Es Django tán simple y fácil de usar?FicherosCarpetas* Incluida la carpeta del proyecto 123. Ficheros y Carpetas ¿Es Django tán simple y fácil de usar? Rails SymfonyFicheros 149 117Carpetas35 29* Incluida la carpeta del proyecto 124. Ficheros y Carpetas ¿Es Django tán simple y fácil de usar? Rails SymfonyFicheros 149 117Carpetas35 29* Incluida la carpeta del proyecto 125. Ficheros y Carpetas ¿Es Django tán simple y fácil de usar? Rails SymfonyDjangoFicheros 149 117 4Carpetas35 291* Incluida la carpeta del proyecto 126. Let’s enjoy 127. Crear nuestro proyectode 4 ficheros ;-‐) 128. Crear nuestro proyectode 4 ficheros ;-‐)$ django-admin startproject dwitter 129. Crear nuestro proyectode 4 ficheros ;-‐)$ django-admin startproject dwitter__init__.py manage.pysettings.pyurls.py 130. Crear nuestro proyecto de 4 ficheros ;-‐)$ django-admin startproject dwitter __init__.py manage.py settings.pyurls.py -‐ ¿Esto es un proyecto... ? Si os ve mi jefe... 131. Crear nuestro proyecto de 4 ficheros ;-‐)$ django-admin startproject dwitter __init__.py manage.py settings.pyurls.py -‐ ¿Esto es un proyecto... ? Si os ve mi jefe... -‐ Sí, disponemos de un proyecto ‘funcional’ en django. 132. sesngs.py 133. Arrancar nuestro proyectode 4 ficheros ;-‐) 134. Arrancar nuestro proyectode 4 ficheros ;-‐) $ cd dwitter $ python manage.py runserver Validating models... 0 errors found Django version 1.1, using settings dwitter.settings Development server is running at http:// 127.0.0.1:8000/ Quit the server with CONTROL-C. 135. Arrancar nuestro proyectode 4 ficheros ;-‐) $ cd dwitter $ python manage.py runserver Validating models... 0 errors found Django version 1.1, using settings dwitter.settings Development server is running at http:// 127.0.0.1:8000/ Quit the server with CONTROL-C. 136. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 137. MVC en DjangoModelo = Model Vista = Template Controlador = URL+View 138. URLs y Vistas• El fichero urls.py actúa como puerta de entrada para las pe7ciones HTTP• Se definen URLs elegantes mediante expresiones regulares que redirigen a funciones de views.py hMp://mysite.com/about/ urls.py ¿urlpaMerns?html views.py ... 139. URLs y Vistas• La función de views.py recibe como parámetros un objeto HhpRequest y todos los parámetros de la URL capturados, teniendo que devolver siempre un objeto HhpResponse HhpRequest(), ... views.py HhpResponse() 140. URLs y Vistas Ejemplo 1: http://mysite.com/time from django.conf.urls.defaults import * from mysite.views import hora_actual urls.py urlpatterns = patterns(, (r^time/$, hora_actual), ) from django.http import HttpResponse from datetime import datetimeviews.py def hora_actual(request): now = datetime.now() html = "Son las %s." % now return HttpResponse(html) 141. URLs y Vistas Ejemplo 2: http://mysite.com/time/plus/2 from django.conf.urls.defaults import * from mysite.views import dentro_de urls.py urlpatterns = patterns(, (r^time/plus/(d{1,2})/$, dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset):views.py offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) 142. URLs y Vistas Ejemplo 2: http://mysite.com/time/plus/2 from django.conf.urls.defaults import * from mysite.views import dentro_de urls.py urlpatterns = patterns(, (r^time/plus/(d{1,2})/$, dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset):views.py offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) 143. ¡Recuerda!: MVC 144. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 145. Templates• Separan la lógica de presentación a una capa independiente. • Ficheros independientes (.html) • Lenguaje independiente (¡para diseñadores!) 146. Templates • Se basan en dos 7pos de objetos: Template() y Context(). • Un objeto Template() con7ene el string de salida que queremos devolver en el HMpResponse (normalmente HTML), pero incluyendo e7quetas especiales de Django. • Un objeto Context() con7ene un diccionario con los valores que dan contexto a una plan7lla, los que deben usarse para renderizar un objeto Template().Template:"Bienvenido, {{ user }}.""Bienvenido, alatar." Context:{user: alatar} 147. Templates• Primera aproximación al obje7vo: Template + Context from django.http import HttpResponse from django.template import Template, Context from datetime import datetime PLANTILLA = """ Son las {{ hora }}. """ def hora_actual(request): now = datetime.now() t = Template(PLANTILLA) c = Context({hora: now}) html = t.render(c) return HttpResponse(html) 148. Templates• Segunda aproximación al obje7vo: 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) 149. Templates• Segunda aproximación al obje7vo: 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) 150. Templates• Segunda aproximación al obje7vo: open(), read(), close()from django.http import HttpResponsefrom django.template import Template, Contextfrom datetime import datetimedef hora_actual(request):now = datetime.now()Bo ring plate fp = open(/home/django/templates/hora.html) boilert = Template(fp.read())fp.close()code!c = Context({hora: now})html = t.render(c)return HttpResponse(html) 151. Templates• Tercera aproximación al obje7vo: get_template() TEMPLATE_DIRS = ( sesngs.py /home/django/templates, ) from django.http import HttpResponse from django.template.loader import get_template from django.template import Context from datetime import datetime def hora_actual(request): now = datetime.now() t = get_template(hora.html) c = Context({hora: now}) html = t.render(c) return HttpResponse(html) 152. Templates• Tercera aproximación al obje7vo: get_template() TEMPLATE_DIRS = ( sesngs.py /home/django/templates, ) from django.http import HttpResponse from django.template.loader import get_template from django.template import Context from datetime import datetime def hora_actual(request): now = datetime.now() t = get_template(hora.html) c = Context({hora: now}) html = t.render(c) return HttpResponse(html) 153. Templates• Tercera aproximación al obje7vo: get_template() TEMPLATE_DIRS = ( sesngs.py /home/django/templates, ) from django.http import HttpResponse from django.template.loader import get_template from django.template import Context from datetime import datetime def hora_actual(request):S7ll now = datetime.now() t = get_template(hora.html) c = Context({hora: now}) html = t.render(c)boring... return HttpResponse(html) 154. Templates• Obje7vo alcanzado: render_to_response() from django.shortcuts import render_to_response from datetime import datetime def hora_actual(request): now = datetime.now() return render_to_response(hora.html, {hora: now}) 155. Templates• Obje7vo alcanzado: render_to_response() from django.shortcuts import render_to_response from datetime import datetime def hora_actual(request): now = datetime.now() return render_to_response(hora.html, {hora: now}) Bori ng...? 156. Templates• Obje7vo alcanzado: render_to_response() from django.shortcuts import render_to_response from datetime import datetime def hora_actual(request): now = datetime.now() return render_to_response(hora.html, {hora: now})AWESOME! 157. Templates: TipTEMPLATE_DIRS = (a) sesngs.py/home/django/templates,) 158. Templates: TipTEMPLATE_DIRS = (Reusa ble a) sesngs.py/home/django/templates,)apps? 159. Templates: TipTEMPLATE_DIRS = (Reusa ble a) sesngs.py/home/django/templates,)apps?b) Alterna7va reu7lizable: TEMPLATE_LOADERS = ( django.template.loaders.filesystem.Loader, django.template.loaders.app_directories.Loader, ) • La carpeta /templates es buscada dentro de cada app. • Conviene incluir una carpeta con el nombre de la app por claridad. return render_to_response(website/index.html) 160. a) Crear la app dwiger.website.b) Incluir la app en sesngs.py.c) Definir una vista para la URL “/” que devuelva el texto “Bienvenidos a dwiger”: ‣/ ‣ timeline(request) ¡Empieza nuestro primer proyecto! 161. Tarea 1: URLs y Vistas a) Definir todas las URLs y vistas (vacías) que va a tener el proyecto: ‣ user//status// ‣ tweet_page(request, tweet_id) ‣ user// ‣ user_page(request, username) ‣ users/ ‣ users_list(request) ‣ user//follow/ ‣ follow_user(request, username) ‣ user//unfollow/ ‣ unfollow_user(request, username) 162. Tarea 1: URLs y Vistas b) Implementar la vista timeline() para que renderice un Hmeline de twiger en una template index.html a parHr de datos hardcodeados en un diccionario. 163. 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 164. FilosoXa y Limitaciones• La sintaxis debe estar desacoplada del HTML/XML.• Los diseñadores saben HTML.• Los diseñadores no saben Python.• No consiste en inventarse un lenguaje.• Una variable no puede cambiar el valor de una variable.• Una template no puede ejecutar código Python. 165. Templates: {{}}Ejemplo templatesHola, {{ username }}. {username: juan}Ejemplo templatesHola, juan. 166. Filters y Tags 167. Filters y Tags 168. Filters y Tagsfilter {{ varible|filter }} 169. Filters y Tagsfilter {{ varible|filter }}inline tag {% tag var1 var2 %} 170. Filters y Tagsfilter {{ varible|filter }}inline tag {% tag var1 var2 %}block tag{% tag var1 %}...{% endtag %} 171. Templates: tags {% %} 172. Templates: tags {% %}comment {% comment %} Bu! {% endcomment %} 173. Templates: tags {% %}comment {% comment %} Bu! {% endcomment %}for {% for elemento in lista %}{{ elemento }}{% endfor %} 174. Templates: tags {% %}comment{% comment %} Bu! {% endcomment %}for{% for elemento in lista %} {{ elemento }} {% endfor %}if {% if username == "Juan" %} Hola Juan, me gustas!== != >< >= >> Publisher.objects.all()[] 262. Previo: __unicode__()>>> Publisher.objects.all()[] 263. Previo: __unicode__()>>> Publisher.objects.all()[] 264. Previo: __unicode__()>>> Publisher.objects.all()[]class Publisher(models.Model):...def __unicode__(self):return self.name 265. Previo: __unicode__()>>> Publisher.objects.all()[]class Publisher(models.Model):...def __unicode__(self):return self.name>>> Publisher.objects.all()[] 266. INSERT 267. INSERT o = Model(...)o.save()a) >>> p = Publisher( ... name=Apress, ... address=2855 Telegraph Avenue, ... city=Berkeley, ... state_province=CA, ... country=U.S.A., ... website=http://www.apress.com/) >>> p.save() 268. INSERT o = Model(...)o.save()a) >>> p = Publisher( ... name=Apress, ... address=2855 Telegraph Avenue, ... city=Berkeley, ... state_province=CA, ... country=U.S.A., ... website=http://www.apress.com/) >>> p.save()manager.create(...)b) >>> p = Publisher.objects.create( ... name=OReilly, ... address=10 Fawcett St., ... city=Cambridge, ... state_province=MA, ... country=U.S.A., ... website=http://www.oreilly.com/) 269. UPDATE 270. UPDATE o.save()>>> ...>>> p.id1 52>>> p.name = Apress Publishing>>> p.save() 271. UPDATE o.save()>>> ...>>> p.id1 52>>> p.name = Apress Publishing>>> p.save() queryset.update(...)n >>> Publisher.objects.all().update(country=USA)2 272. DELETE 273. DELETEo.delete()>>> ...>>> p.id1 52>>> p.delete() 274. DELETEo.delete()>>> ...>>> p.id1 52>>> p.delete()queryset.delete()>>> ps = Publisher.objects.all()n >>> ps.delete() 275. SELECT de 1 resultado 276. SELECT de 1 resultado .get(...)>>> Publisher.objects.get(name="Apress") 277. SELECT de 1 resultado .get(...)>>> Publisher.objects.get(name="Apress")>>> Publisher.objects.get(name="Anaya")Traceback (most recent call last):...DoesNotExist: Publisher matching query does not exist. 278. SELECT de 1 resultado .get(...)>>> Publisher.objects.get(name="Apress")>>> Publisher.objects.get(name="Anaya")Traceback (most recent call last):...DoesNotExist: Publisher matching query does not exist.>>> 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.} 279. SELECT de N resultados 280. SELECT de N resultados .all()>>> Publisher.objects.all()[, ] 281. SELECT de N resultados .all()>>> Publisher.objects.all()[, ].filter(...)>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")[] 282. SELECT de N resultados .all()>>> Publisher.objects.all()[, ].filter(...)>>> Publisher.objects.filter(country="U.S.A.", state_province="CA")[] .exclude(...)>>> Publisher.objects.exclude(country="U.S.A.", state_province="CA")[] 283. SELECT de N resultadosen evuelv¡Ds, no .all()uerySetQ li stas! >>> Publisher.objects.all() [, ] .filter(...) >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [].exclude(...) >>> Publisher.objects.exclude( country="U.S.A.", state_province="CA") [] 284. get(), filter() y exclude() 285. get(), filter() y exclude() Modelo.objects.filter(campo1="valor1", campo2="valor2")Los parámetros pueden indicar mucho más que igualdad (=) 286. get(), filter() y exclude() Modelo.objects.filter(campo1="valor1", campo2="valor2") Los parámetros pueden indicar mucho más que igualdad (=)campo__exact=campo__gt=0 campo__startswith=campo__iexact= campo__gte=0campo__istartswith=campo__contains= campo__lt=0 campo__endswith=campo__icontains=campo__lte=0campo__iendswith=campo__isnull=T|Fcampo__in=[ ,]campo__range=( ,)campo__day=31campo__month=12 campo__year=2010 287. ORDER BY 288. ORDER BY.order_by(...)>>> Publisher.objects.order_by("name")[, ] 289. ORDER BY.order_by(...)>>> Publisher.objects.order_by("name")[, ]>>> Publisher.objects.order_by("-name")[, ] 290. ORDER BY.order_by(...) >>> Publisher.objects.order_by("name") [, ] >>> Publisher.objects.order_by("-name") [, ]MúlHples campos:>>> Publisher.objects.order_by("-name", "country")[, ] 291. ORDER BY ¡También devu elve .order_by(...)uer y Sets!Q >>> Publisher.objects.order_by("name") [, ] >>> Publisher.objects.order_by("-name") [, ]MúlHples campos:>>> Publisher.objects.order_by("-name", "country")[, ] 292. Slicing 293. Slicing [n:m]>>> Publisher.objects.order_by("name")[0]>>> Publisher.objects.order_by("name")[:2][, ]>>> Publisher.objects.order_by("name")[1:2][] 294. Slicing [n:m]>>> Publisher.objects.order_by("name")[0]>>> Publisher.objects.order_by("name")[:2][, ] LIMIT>>> Publisher.objects.order_by("name")[1:2][] 295. Slicing [n:m]>>> Publisher.objects.order_by("name")[0]>>> Publisher.objects.order_by("name")[:2][, ] LIMIT>>> Publisher.objects.order_by("name")[1:2][]O FFSET 296. Related Objects 297. Related ObjectsOneToOneField class Coche(models.Model):1motor = OneToOneField(Motor) class Motor(models.Model):1... 298. Related ObjectsOneToOneFieldclass Coche(models.Model):1 motor = OneToOneField(Motor)class Motor(models.Model):1 ... ¿Cómo usamos la relación desde las instancias?Gracias a nosotros>>> c.motor 299. Related ObjectsOneToOneFieldclass Coche(models.Model):1 motor = OneToOneField(Motor)class Motor(models.Model):1 ... ¿Cómo usamos la relación desde las instancias?Gracias a nosotros Gracias a Django>>> c.motor >>> m.coche 300. Related Objects 301. Related ObjectsForeignKeyFieldclass Blog(models.Model):1 ...class Post(models.Model):n blog = ForeignKeyField(Blog) 302. Related Objects ForeignKeyField class Blog(models.Model): 1 ... class Post(models.Model): n blog = ForeignKeyField(Blog) ¿Cómo usamos la relación desde las instancias?Gracias a nosotros Gracias a Django>>> p.blog >>> b.post_set.all()[, ...] 303. Related Objects 304. Related ObjectsManyToManyFieldclass Post(models.Model):n tags = ManyToManyField(Tag)class Tag(models.Model):m ... 305. Related ObjectsManyToManyFieldclass Post(models.Model):n tags = ManyToManyField(Tag)class Tag(models.Model): m... ¿Cómo usamos la relación desde las instancias? Gracias a nosotros Gracias a Django>>> p.tags.add(t1, t2) >>> t.post_set.add(p1, p2)>>> p.tags.all() >>> t.post_set.all()[, ...] [, ...] 306. Related Objects 307. Related ObjectsEn todas ellas podemos renombrar el puntero inversoclass Blog(models.Model):1 ...class Post(models.Model):n blog = ForeignKeyField(Blog, related_name=posts) 308. Related ObjectsEn todas ellas podemos renombrar el puntero inverso class Blog(models.Model):1... class Post(models.Model):nblog = ForeignKeyField(Blog, related_name=posts)Gracias a nosotros Gracias a Django>>> p.blog >>> b.posts.all()[, ...] 309. Related ObjectsEn todas ellas podemos renombrar el puntero inversoclass Blog(models.Model): 1...class Post(models.Model): nblog = ForeignKeyField(Blog, related_name=posts) Gracias a nosotrosGracias a Django >>> p.blog>>> b.posts.all() [, ...]Cuando haya 2 relaciones entre 2 modelos, será obligatorio 310. Y la guinda final: ¡Todo es LAZY! 311. Laziness 312. Laziness• Las consultas sólo se ejecutarán cuando realmente se necesite obtener los objetos. En las siguientes situaciones:• Iteraciones for p in Publisher.objects.all():• Slicing Publisher.objects.filter(country=USA)[0]• Serialización [Caché]• repr()[]• len() !!! len(Publisher.objects.all())• list()list(Publisher.objects.all())• bool()if Publisher.objects.filter(country=USA): 313. a) Insertar varios Tweets desde la shell.b)Modificar views.timeline para que uHlice los Tweets reales de la BD.c) Implementar la vista tweet_page() como permalink de un tweet: ‣ URL: user//status/ ‣ View: tweet_page ‣ Template: tweet_page.html (Descargar)d)Lanzar Http404 si no existe el tweet_id.e) shortcut!: get_object_or_404() Usando el ORM 314. Profiles 315. 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. 316. Profile models.py 317. Profile models.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) 318. Profile models.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) 319. Profile models.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) ... 320. Profile models.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) ... sesngs.pyAUTH_PROFILE_MODULE = "website.Profile" 321. Profile models.py class Profile(models.Model):user = models.OneToOneField(User, unique=True)bio = models.CharField(blank=True, max_length=200)... sesngs.py AUTH_PROFILE_MODULE = "website.Profile"• Cada objeto User de django.contrib.auth dispone de un método get_profile() que nos permiHrá acceder al Profile. 322. Profile• Donde tengamos el User tendremos el Profile.• Donde tengamos el Profile, tendremos el User. 323. Profile>>> from django.contrib.auth.models import User>>> u = User.objects.get(id=1)>>> type(u)>>> profile = u.get_profile()>>> type(profile)• Donde tengamos el User tendremos el Profile.• Donde tengamos el Profile, tendremos el User. 324. 1 User = 1 Profile ¿Cuándo se crea un User? 325. 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_finishedhMp://docs.djangoproject.com/en/dev/ref/signals/ 326. Signals 327. Signalsdef profile_signal_callback(sender, **kwargs): 1if kwargs.get(created):profile = Profile()profile.user = kwargs.get(instance)profile.save()from django.db.models.signals import post_savepost_save.connect(profile_signal_callback, sender=User,dispatch_uid="users-profilecreation-signal") 328. Signalsdef profile_signal_callback(sender, **kwargs): 1if kwargs.get(created):profile = Profile() 2profile.user = kwargs.get(instance)profile.save()from django.db.models.signals import post_savepost_save.connect(profile_signal_callback, sender=User,dispatch_uid="users-profilecreation-signal") 329. Signalsdef profile_signal_callback(sender, **kwargs): 1if kwargs.get(created):profile = Profile() 2profile.user = kwargs.get(instance)profile.save()from django.db.models.signals import post_save 3post_save.connect(profile_signal_callback, sender=User,dispatch_uid="users-profilecreation-signal") 330. Signalsdef profile_signal_callback(sender, **kwargs): 1if kwargs.get(created):profile = Profile() 2profile.user = kwargs.get(instance)profile.save()from django.db.models.signals import post_save 3post_save.connect(profile_signal_callback, sender=User,4dispatch_uid="users-profilecreation-signal") 331. Signalsdef profile_signal_callback(sender, **kwargs): 1if kwargs.get(created):profile = Profile() 2profile.user = kwargs.get(instance)profile.save()from django.db.models.signals import post_save3post_save.connect(profile_signal_callback, sender=User,4dispatch_uid="users-profilecreation-signal")Puede estar en cualquier app de nuestro proyecto.Se recomienda models.py 332. a) Crear el modelo Profileb)Crear signal para agregar un objeto Profile a cada objeto User creado.c) Eliminar BD.d)Hacer syncdbUsers en dwiger 333. Followers 334. Profile models.py 335. Profilemodels.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) 336. Profilemodels.pyclass Profile(models.Model): user = models.OneToOneField(User, unique=True) bio = models.CharField(blank=True, max_length=200) followers = models.ManyToManyField("self", blank=True, 337. Profilemodels.pyclass 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, 338. Profilemodels.pyclass 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") 339. Profilemodels.pyclass 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") • 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 340. a) Añadir ManyToMany para los followers.b)Eliminar BD.c) Hacer syncdb Users en dwiger 341. 1,2,3 Borrar la BD.... 1,2,3... Borrar la BD 342. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 343. CRUD: Create, Retrieve, Update & Delete 344. django.contrib.admin12 3 345. django.contrib.admin12 3 346. django.contrib.admin1 347. Django admin: Instalación urls.pyfrom django.conf.urls.defaults import *# Uncomment the next two lines to enable the admin:# from django.contrib import admin1# admin.autodiscover()urlpatterns = patterns(,...2 # (r^admin/, include(admin.site.urls)),...) 348. Django admin: Instalación urls.pyfrom django.conf.urls.defaults import *# Uncomment the next two lines to enable the admin:from django.contrib import admin1admin.autodiscover()urlpatterns = patterns(,...2 (r^admin/, include(admin.site.urls)),...) 349. Django admin: Instalación sesngs.pyINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,...) 350. Django admin: Instalación sesngs.pyINSTALLED_APPS = (django.contrib.auth,django.contrib.contenttypes,django.contrib.sessions,django.contrib.sites,django.contrib.admin, 1...) 351. Actualizando la BD 352. Actualizando la BD$ python manage.py syncdb Creating table django_admin_log Installing index for admin.LogEntry model Admin lista para usar 353. ¿Y nuestra app?? 354. ¿Y nuestra app? 355. 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) 356. a) Configurar urls.pyb)Configurar sesngs.pyc) Hacer syncdbd)Comprobar que no está Tweet.e) Añadir admin.pyf) Probar Administración. Instalar Admin 357. Fixtures 358. 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: 359. 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 360. 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 • Se cargan uHlizando: python manage.py loaddata • Si se llaman iniAal_data y están dentro de la carpeta fixtures de la app, se cargan al ahcer el syncdb. 361. a) Crear la carpeta website/fixtures.b)Introducir datos desde el panel Admin y hacer un dumpdata que guarde un fixture con nombre initial_data.json en la carpeta fixtures.c) Hacer syncdbEl poder de los fixtures 362. Tarea 5: Avance en dwiger a) Implementar la vista user_page() para ofrecer un perfil de usuario con su Hmeline personal:‣ URL: user//‣ View: user_page‣ Template: user_page.html (Descargar) 363. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 364. Formularios 365. Clases involucradas 366. Clases involucradasWidget Componente visual equivalente a HTML TextInput CheckboxInput 367. Clases involucradasWidget Componente visual equivalente a HTML TextInput CheckboxInput FieldLógica de un campo, asociado a un Widget EmailField widget, initial, error, ... IPAddressField 368. Clases involucradasWidget Componente visual equivalente a HTML TextInput CheckboxInput FieldLógica de un campo, asociado a un Widget EmailField widget, initial, error, ... IPAddressField FormConjunto de Fields de un formulario ContactForm [nombre, email, telefono, mensaje, ...] 369. Fields 370. Fields■ BooleanField■ IPAddressField■ CharField ■ MultipleChoiceField■ ChoiceField ■ NullBooleanField■ TypedChoiceField■ RegexField■ DateField ■ SlugField■ DateTimeField ■ TimeField■ DecimalField■ URLField■ EmailField■ ComboField■ FileField ■ MultiValuefield■ FilePathField ■ SplitDateTimeField■ FloatField■ ModelChoiceField■ ImageField■ ModelMultipleChoiceField■ IntegerField 371. Fields■ BooleanField■ IPAddressField■ CharField ■ MultipleChoiceField■ ChoiceField ■ NullBooleanField■ TypedChoiceField■ RegexField■ DateField ■ SlugField■ DateTimeField ■ TimeField■ DecimalField■ URLField■ EmailField■ ComboField■ FileField ■ MultiValuefield■ FilePathField ■ SplitDateTimeField■ FloatField■ ModelChoiceField■ ImageField■ ModelMultipleChoiceField■ IntegerField 372. Creación de un Form• Paso 1/3: Definición del formulario en forms.pyfrom 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) 373. Creación de un Form• Paso 2/3: Maquetación del formulario en su templateContact us{% if form.errors %}Please correct the error{{ form.errors|pluralize }} below.{% endif %}{{ form.as_table }} 374. Creación de un Form• Paso 3/3: Programación de la vista en views.pyfrom django.shortcuts import render_to_responsefrom 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_to_response(contact_form.html, {form: form}) 375. Creación de un Form• Paso 3/3: Programación de la vista en views.pyfrom django.shortcuts import render_to_responsefrom mysite.contact.forms import ContactFormdef contact(request): if request.method == POST: Pa gern 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_to_response(contact_form.html, {form: form}) 376. Creación de un Form• Paso 3/3: Programación de la vista en views.pyfrom django.shortcuts import render_to_responsefrom mysite.contact.forms import ContactFormdef contact(request): if request.method == POST: Pa gern 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_to_response(contact_form.html, {form: form}) 377. Creación de un Form• Paso 3/3: Programación de la vista en views.pyfrom django.shortcuts import render_to_responsefrom mysite.contact.forms import ContactFormdef contact(request): if request.method == POST:Pa gern 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_to_response(contact_form.html, {form: form}) 378. Validación propia Podemos programar validación extra asociada a cada Field del formulario escribiendo un método clean_:from 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 message 379. Validación propia Podemos programar validación extra asociada a cada Field del formulario escribiendo un método clean_:from 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 message 380. Maquetación propia Podemos personalizar la maquetación tanto como queramos, prescindiendo de las ayudas de form.as_table:...{{ form.subject.errors }} Para los diseñadores:Subject:{{ form.subject }} ul.errorlist {...{{ form.email.errors }}}E-mail:.errorlist li {{{ form.email }} ... }...... 381. Forms a parHr de Models: El COLMO del DRY 382. Forms a par/r de Modelsfrom django.db import modelsclass Author(models.Model):models.py 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 Author forms.py class AuthorForm(forms.ModelForm):class Meta:model = Authorexclude = (country,) 383. a) Crear un Form que permita publicar tweets desde Hmeline.html al usuario que esté logueado desde django.contrib.admin (no tenemos login propio).Primer Form en dwiger 384. Tarea 6: Avance en dwiger a) Implementar la vista users_list() para visualizar la lista de usuarios:‣ URL: users/‣ View: users_list‣ Template: users_list.html (Descargar) 385. Índice1. Python 2. Djangoa. Introducción a. Introducciónb. Tipos de datos b. URLs y Vistasc. Operadores c. Templates Proyectod. Usos frecuentes d. Modeloe. Estructurase. Administraciónf. Sentencias f. Formulariosg. Ejerciciog. Magia avanzada 386. Magia avanzada 387. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 388. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 389. Views avanzadas¡El primer parámetro de paherns() sirve de algo! from django.conf.urls.defaults import * urlpatterns = patterns(, (r^hello/$, mysite.views.hello), (r^time/$, mysite.views.current_datetime), (r^time/plus/(d{1,2})/$, mysite.views.hours_ahead), ) 390. Views avanzadas¡El primer parámetro de paherns() sirve de algo! from django.conf.urls.defaults import * urlpatterns = patterns(, (r^hello/$, mysite.views.hello), (r^time/$, mysite.views.current_datetime), (r^time/plus/(d{1,2})/$, mysite.views.hours_ahead), ) from django.conf.urls.defaults import * urlpatterns = patterns(mysite.views, (r^hello/$, hello), (r^time/$, current_datetime), (r^time/plus/(d{1,2})/$, hours_ahead), ) 391. Views avanzadasEn ficheros urls.py que gesHonen varias apps...from django.conf.urls.defaults import *urlpatterns = patterns(mysite.views,(r^hello/$, hello),(r^time/$, current_datetime),(r^time/plus/(d{1,2})/$, hours_ahead),)urlpatterns += patterns(weblog.views,(r^tag/(w+)/$, tag),) 392. Views avanzadasEn ficheros urls.py que gesHonen varias apps...from django.conf.urls.defaults import *urlpatterns = patterns(mysite.views,(r^hello/$, hello),(r^time/$, current_datetime),(r^time/plus/(d{1,2})/$, hours_ahead),)urlpatterns += patterns(weblog.views,(r^tag/(w+)/$, tag),) 393. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 394. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 395. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 396. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 397. NUNCA 398. NUNCAINFRAVALORÉIS 399. NUNCAINFRAVALORÉIS PODERel 400. NUNCAINFRAVALORÉIS PODERel PONYde un 401. NUNCAINFRAVALORÉIS PODERel PONYde un ROSA 402. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 403. Views avanzadas¿Dónde somos capaces de reu/lizar código entre apps? 404. Views avanzadas Generic ViewsVistas con funcionalidad genérica parametrizable mediante un diccionario de Extra Op/ons Las tuplas de paherns() pueden tener 3 elementosfrom django.conf.urls.defaults import *from mysite import viewsurlpatterns = patterns(,(r^foo/$, views.foobar_view, {template_name: template1.html}),(r^bar/$, views.foobar_view, {template_name: template2.html}),) 405. Views avanzadas from django.views.generic.simple import direct_to_template Renderiza directamente la template indicadafrom django.conf.urls.defaults import *from django.views.generic.simple import direct_to_templateurlpatterns = patterns(,(r^about/$, direct_to_template, {template: about.html})) Es la Generic View más simple y más uHlizada 406. a) 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: logout.html (Descargar)Extra OpHons en urls.py 407. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 408. Context ProcessorsProblema ! ! ! ! ! ! ! ! 409. Context Processors Solución: el objeto RequestContext() c = RequestContext(request, {tweets: tweets})• Sus7tuye a Context().• Recibe un HMpRequest() antes del diccionario.• Automá7camente alimenta nuestro diccionario con todos los diccionarios devueltos por los Context Processors que tengamos habilitados. 410. Context Processors ¿Context Processors? Son funciones.• Reciben un HMpRequest() como único parámetro.• Devuelven un diccionario para ser usado como Context(). 411. Context Processors ¿Context Processors? Son funciones.• Reciben un HMpRequest() como único parámetro.• Devuelven un diccionario para ser usado como Context().def ip_address_processor(request):return {ip_address: request.META[REMOTE_ADDR]} 412. Context Processors ¿Context Processors? Son funciones.• Reciben un HMpRequest() como único parámetro.• Devuelven un diccionario para ser usado como Context().def ip_address_processor(request):return {ip_address: request.META[REMOTE_ADDR]}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",) 413. Context Processors¿Qué ocurre con render_to_response()?def some_view(request):# ...return render_to_response(my_template.html, my_data_dictionary, context_instance=RequestContext(request)) 414. Context Processors¿Qué ocurre con render_to_response()?def some_view(request): # ...return render_to_response(my_template.html, my_data_dictionary, context_instance=RequestContext(request)) 415. Context Processors¿Qué ocurre con render_to_response()?def some_view(request): # ...return render_to_response(my_template.html, my_data_dictionary, context_instance=RequestContext(request)) Consejofrom django.shortcuts import render_to_responsefrom django.template import RequestContextdef render_response(req, *args, **kwargs): kwargs[context_instance] = RequestContext(req) return render_to_response(*args, **kwargs) 416. a) Crear un fichero
[email protected] en la raíz del proyecto que implemente la función render_response().b)Cambiar todas las vistas para que uHlicen render_response() e incluyan así todos los ContextProcessors disponibles.ContextProcessors en dwiger 417. c) Añadir en la cabecera de todas las páginas (en base.html) un mensaje de bienvenida al usuario logueado: Bienvenido, .d)Si no hay ningún usuario logueado, habrá que mostrar un enlace Entrar que nos lleve a /login.ContextProcessors en dwiger 418. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 419. Template LibraryNos permite extender el sistema de templates de Django con Filters y Tags propios 420. Template LibraryNos permite extender el sistema de templates de Django con Filters y Tags propios Uso{% load milibreria %}...{{ variable|mifiltro:"param" }}...{% mitag param1 param2 %} 421. Template LibraryNos permite extender el sistema de templates de Django con Filters y Tags propios UsoCreación{% load milibreria %}...{{ variable|mifiltro:"param" }}...{% mitag param1 param2 %} 422. 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. 423. Custom FiltersUn Filter es una función Python que:• Recibe 1 o 2 argumentos: (value [, arg]).• Siempre devuelve algo: el resultado, value o "".• Falla silenciosamente: no lanza excepciones. from django import template register = template.Library()Ejemplodef cut(value, arg= ): return value.replace(arg, ) register.filter(cut, cut) 424. Custom FiltersUn Filter es una función Python que:• Recibe 1 o 2 argumentos: (value [, arg]).• Siempre devuelve algo: el resultado, value o "".• Falla silenciosamente: no lanza excepciones. from django import template register = template.Library() @register.filter(name=cut) def cut(value, arg= ): return value.replace(arg, ) 425. Custom FiltersUn Filter es una función Python que: • Recibe 1 o 2 argumentos: (value [, arg]). • Siempre devuelve algo: el resultado, value o "". • Falla silenciosamente: no lanza excepciones. from django import template Py thon register = template.Library()2.4 se hizo @register.filter(name=cut) sexydef cut(value, arg= ): return value.replace(arg, ) 426. a) Crear un Filter llamado |mention que al detectar un “@usuario” convierta ese texto en un enlace al perfil de dwiger de ese usuario.Nuestro propio Filter en dwiger 427. 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 • Son inline• Reciben 1 argumento • Reciben n argumentos• Devuelven un string • Devuelven un diccionario• Insertan su propio fragmento de template 428. SimpleTagsEjemplo: Devolver la hora actual formateada.{% current_time "%Y-%m-%d %I:%M %p" %} 429. SimpleTags Ejemplo: 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 430. InclusionTagsEjemplo: Mostar un link de ‘follow’ o uno de ‘unfollow’. {% follow_or_unfollow_link user.get_profile otherprofile %} 431. InclusionTagsEjemplo: Mostar un link de ‘follow’ o uno de ‘unfollow’. {% follow_or_unfollow_link user.get_profile otherprofile %} @register.inclusion_tag(website/follow_or_unfollow.html) def follow_or_unfollow_link(me, user): subcontext = {} if user in me.following.all(): subcontext[is_friend] = True else: subcontext[is_friend] = False subcontext[target_user] = user return subcontext 432. InclusionTagsEjemplo: Mostar un link de ‘follow’ o uno de ‘unfollow’. {% follow_or_unfollow_link user.get_profile otherprofile %} @register.inclusion_tag(website/follow_or_unfollow.html) def follow_or_unfollow_link(me, user): subcontext = {} if user in me.following.all(): subcontext[is_friend] = True else: subcontext[is_friend] = False subcontext[target_user] = user return subcontext {% if is_friend %} unfollow {% else %} follow {% endif %} 433. a) Crear un Tag llamado follow_or_unfollow_link que permita pintar un enlace de ‘follow’ o ‘unfollow’ junto a cada usuario dwiger que aparece listado en users_page.htmlNuestro propio TemplateTag en dwiger 434. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 435. Middleware Nos permite escribir funcionalidad reu7lizable que se inserta en el flujo de ejecución de Django 436. 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."""# ... 437. 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,) 438. 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... 439. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 440. InternacionalizaciónOfrece integración con la librería GNU gehext 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.mo 441. Internacionalización• ¿Cómo indicar qué strings deben ser traducidos?• GesHón cómoda de singulares y plurales 442. Internacionalización• ¿Cómo indicar qué strings deben ser traducidos?from django.utils.translation import ugettext as _print _("Cadena de texto")• GesHón cómoda de singulares y plurales 443. Internacionalización• ¿Cómo indicar qué strings deben ser traducidos?from django.utils.translation import ugettext as _print _("Cadena de texto")• GesHón cómoda de singulares y pluralesfrom django.utils.translation import ungettextfrase = ungettext("Hay %(total)d resultado","Hay %(total)d resultados", total)% { total: total } 444. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 445. caching• Si queremos escalar nuestro proyecto rápidamente.... Cache! • Recomendado = memcached• Acceder a la BD es caro, muy caro.• El Hardware es “gra7s” en comparación con op7mizar código op7mizado.• Ejemplo (Facebook): 446. caching• Si queremos escalar nuestro proyecto rápidamente.... Cache! • Recomendado = memcached• Acceder a la BD es caro, muy caro.• El Hardware es “gra7s” en comparación con op7mizar código op7mizado.• Ejemplo (Facebook): 300+Tb Memcached 447. cachingviewsfrom django.views.decorators.cache import cache_page@cache_page(60 * 15)def my_view(request):... 448. caching views from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request): ...templates {% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %} 449. cachinglow level 450. cachinglow level>>> from django.core.cache import cache>>> cache.set(my_key, hello, world!, 30)>>> cache.get(my_key)hello, world!• Podemos cachear cualquier 7po de objeto que se pueda serializar.• QuerySets• Listas• ... 451. memcached DEMO 452. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 453. Deploying Django1. hgp://virtualenv.openplans.org/2. hgp://pip.openplans.org/3. hgp://fabfile.org/ 454. Deploying DjangoVirtualenv + PIP [+ Fabric] 1. hgp://virtualenv.openplans.org/ 2. hgp://pip.openplans.org/ 3. hgp://fabfile.org/ 455. Virtualenv• Independencia completa de las librerías del sitema.• Cada proyecto 7ene su juego de librerías en la versión que necesita• Sin miedo a actualizar• Sin miedo a migrar• etc... 456. Virtualenv• Independencia completa de las librerías del sitema.• Cada proyecto 7ene su juego de librerías en la versión que necesita• Sin miedo a actualizar• Sin miedo a migrar• etc...crear$ virtualenv --no-site-packages mi_entorno 457. Virtualenv• Independencia completa de las librerías del sitema.• Cada proyecto 7ene su juego de librerías en la versión que necesita• Sin miedo a actualizar• Sin miedo a migrar• etc...crear$ virtualenv --no-site-packages mi_entornoac/var$ source mi_entorno/bin/activate 458. PIP• Gestor de paquetes del siglo 21 :D• Permite especificar un fichero de REQUIREMENTS con un listado de paquetes a instalar. 459. PIP• Gestor de paquetes del siglo 21 :D• Permite especificar un fichero de REQUIREMENTS con un listado de paquetes a instalar. Django==1.2.3 psycopg2 feedparser==4.1 stripogram==1.5 GChartWrapper==0.8pip install -E mi_entorno -r REQUIREMENTS 460. a) Crear un entorno virtualb)Instalar Django==1.0c) Probar django.VERSION Nuestro primer Virtualenv + PIP 461. Fabric“ Repetition leads to boredom, boredom to horrifying mistakes,horrifying mistakes to God-I-wish-I-was-still-bored 462. Fabric“ Repetition leads to boredom, boredom to horrifying mistakes,horrifying mistakes to God-I-wish-I-was-still-bored fabfile.pyenv.user = "example"env.hosts = ["example.com"]def deploy(): run(svn up /home/example/) sudo(/etc/init.d/lighttpd restart) 463. Fabric“ Repetition leads to boredom, boredom to horrifying mistakes,horrifying mistakes to God-I-wish-I-was-still-bored fabfile.pyenv.user = "example"env.hosts = ["example.com"]def deploy(): run(svn up /home/example/) sudo(/etc/init.d/lighttpd restart) usofabric deploy 464. nginx + Gunicornnginx • nginx [engine x] is a HTTP and reverse proxy server. • Con una configuración muy sencilla podremos u7lizarlo como proxy inverso a gunicorn. • hMp://gunicorn.org/gunicorn • Servidor Web WSGI implementado en Python • Facilidades de puesta en marcha de proyectos django • Fácilmente configurable usando nginx • hMp://nginx.org/ 465. Magia avanzada1. Views avanzadas2. Context Processors3. Custom Template Filters & Tags4. Middleware5. Internacionalización6. Caching7. Despliegue8. Apps recomendadas 466. Apps 467. django-‐south 468. django-‐south hMp://south.aeracode.org/• Sistema inteligente para realizar de manera automá7ca 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 an7guo Modelo a uno nuevo... south!• Necesito que ... south! 469. django-‐southcrear primer schema$ python manage.py schemamigration website --initialcrear 2-‐* migración $ python manage.py schemamigration website --autoaplicar migraciones$ python manage.py migrate 470. django-‐south hMp://south.aeracode.org/crear primer schema$ python manage.py schemamigration website --initialcrear 2-‐* migración $ python manage.py schemamigration website --autoaplicar migraciones$ python manage.py migrate 471. django-‐haystack hMp://haystacksearch.org/ 472. django-‐haystack• “EL” Sistema de búsquedas para Django• Funciona con varios sistemas de Indexación• Solr, Xapian, Whoosh• Features:• ‘More like this’• Face7ng• Highligh7ng• Spelling Sugges7on• etc... hMp://haystacksearch.org/ 473. django-‐registra/onhMp://bitbucket.org/ubernostrum/django-‐registra7on/ 474. django-‐registra/on• Sistema completo para la ges7ón de usuarios.• Desde el registro, ac7vación etc...• DRY!!• Instalación muy sencilla.• Recomedado ++hMp://bitbucket.org/ubernostrum/django-‐registra7on/ 475. django-‐registra/onhMp://bitbucket.org/ubernostrum/django-‐registra7on/ 476. django-‐registra/on/ac7vate/complete//ac7vate/// register// register/complete// register/closed// login// logout// password/change// password/change/done// password/reset// password/reset/confirm// password/reset/complete// password/reset/done// reac7vate/ hMp://bitbucket.org/ubernostrum/django-‐registra7on/ 477. django-‐socialregistra/onhMp://github.com/flashingpumpkin/django-‐socialregistra7on 478. django-‐socialregistra/on• Configuración sencilla• Auten7cación con:• twiMer, facebook, oauth, openid• Integración perfecta con contrib.authhMp://github.com/flashingpumpkin/django-‐socialregistra7on 479. django-‐debug-‐toolbarhMp://github.com/robhudson/django-‐debug-‐toolbar 480. django-‐celery 481. django-‐celery• 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...) 482. django-‐celeryfrom celery.decorators import task@taskdef add(x, y):return x + y>>> result = add.delay(4, 4)>>> result.wait() # wait for and return the result8 483. django-‐celeryfrom celery.decorators import task• Las Task son simples funciones (O class si queremos)@taskdef add(x, y):• Python 100% el retorno será el resultadoreturn x + y• Usamos el decorador @task para registrarla• El método .delay sobre cualquier Task lo >>> result = add.delay(4, 4) ejecuta en background.>>> result.wait() # wait for and return the result8 • Podemos esperar a que un Worker ejecute la tarea o seguir haciendo otras acciones. 484. dajaxproject hMp://dajaxproject.com 485. dajaxproject• Comunicación AJAX muy sencilla• CrossBrowsing• Muy ú7l si no sabemos demasiado JS• Dajaxice no require ningún Framework de JS• Dajax puede usar cualquiera de los más conocidos (Prototype, jQuery, MooTools...) hMp://dajaxproject.com 486. hMp://dajaxproject.com 487. hMp://dajaxproject.com 488. django-‐locale-‐urlhMp://code.google.com/p/django-‐localeurl/ 489. django-‐locale-‐url• Nos permite especificar el idioma en la urlwww.example.com/en/www.example.com/es/• Mejoras en el SEO• Cada página 7ene una única url.• Configuración no tan sencilla, pero interesante. hMp://code.google.com/p/django-‐localeurl/ 490. django-‐pistonhMp://bitbucket.org/jespern/django-‐piston/wiki/Home 491. django-‐piston• Framework para crear APIs RESTful• Muy fácil instalación• Serialización a:• JSON, YAML, Python Pyckle, XML ...• OAuth• Recomendado +++++hMp://bitbucket.org/jespern/django-‐piston/wiki/Home 492. django-‐sentryhMp://github.com/dcramer/django-‐sentry 493. django-‐command-‐extensions hMp://code.google.com/p/django-‐command-‐extensions/ 494. django-‐command-‐extensions• Extensión para “manage.py”• Muchas u7lidades 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.hMp://code.google.com/p/django-‐command-‐extensions/ 495. django-‐command-‐extensions 496. django-‐command-‐extensions 497. django-‐command-‐extensions 498. django-‐command-‐extensions 499. Textmate + DjangohMps://bitbucket.org/bkerr/django-‐textmate-‐bundles 500. Textmate + Django• Shortcuts para crear:• Modelos• Fields• Filters• TemplateTags• Forms• AdminDurante el curso lo hemos u7lizado.hMps://bitbucket.org/bkerr/django-‐textmate-‐bundles 501. La punta del iceberg 502. hgp://www.djangobook.com/ 503. How to ... using Django? 504. Desarrollo web ágil con Python y DjangoJorge Bas7da PérezJaime Irurzun Graña
[email protected]@gmail.com @jorgebas7da @jaimeirurzun