Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introducción Django

Betabeers
August 05, 2012
400

Introducción Django

Betabeers

August 05, 2012
Tweet

Transcript

  1. • Legible • Produc-vo • Portable • Extenso • Integrable

    • ...  y  Diver-do Sintaxis  intui+va  y  estricta Entre  1/3  y  1/5  más  conciso  que  Java  o  C++ GNU/Linux,  Windows,  Mac  OS  X,  ... Standard  Library,  Third  par+es C,  C++,  Java,  .NET,  COM,  WS,  CORBA,  ...
  2. El  Intérprete $ python holamundo.py hola mundo! $ Modo  Batch

    #!/usr/bin/env python print "hola mundo!" holamundo.py
  3. El  Intérprete $ python Python 2.6.5 (r265:79063, Apr 16 2010,

    13:09:56) [GCC 4.4.3] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> print "hola mundo!" hola mundo! Modo  Interac0vo $ python holamundo.py hola mundo! $ Modo  Batch #!/usr/bin/env python print "hola mundo!" holamundo.py
  4. Tipos  de  datos  h>p://docs.python.org/library/stdtypes.html object 1234 3.1415 int float 35L

    long True False bool 'spam' "guido's" """n lines""" str [1, [2, 'three'], 4] list
  5. Tipos  de  datos  h>p://docs.python.org/library/stdtypes.html object 1234 3.1415 int float 35L

    long True False bool 'spam' "guido's" """n lines""" str [1, [2, 'three'], 4] list {'food': 'spam', 'taste': 'yum'} dict
  6. Tipos  de  datos  h>p://docs.python.org/library/stdtypes.html object 1234 3.1415 int float 35L

    long True False bool 'spam' "guido's" """n lines""" str [1, [2, 'three'], 4] list {'food': 'spam', 'taste': 'yum'} dict (1, 'spam', 4, 'U') tuple
  7. Tipos  de  datos  h>p://docs.python.org/library/stdtypes.html object 1234 3.1415 int float 35L

    long True False bool 'spam' "guido's" """n lines""" str [1, [2, 'three'], 4] list {'food': 'spam', 'taste': 'yum'} dict (1, 'spam', 4, 'U') tuple ¡Tipado   dinámico!
  8. Operadores numéricos a + b a - b a *

    b a / b a % b -a +a a ** b  h>p://docs.python.org/library/operator.html
  9. Operadores numéricos a + b a - b a *

    b a / b a % b -a +a a ** b comparadores a < b a <= b a > b a >= b a == b a != b  h>p://docs.python.org/library/operator.html
  10. Operadores numéricos a + b a - b a *

    b a / b a % b -a +a a ** b comparadores a < b a <= b a > b a >= b a == b a != b lógicos a or b a and b not a  h>p://docs.python.org/library/operator.html
  11. Usos  frecuentes:  list >>> nums = [1, 2, 3] >>>

    nums[0] 1 >>> nums.append(4) >>> print nums [1, 2, 3, 4] >>> 2 in nums True
  12. Usos  frecuentes:  list >>> nums = [1, 2, 3] >>>

    nums[0] 1 >>> nums.append(4) >>> print nums [1, 2, 3, 4] >>> 2 in nums True >>> len(nums) 4
  13. Usos  frecuentes:  str >>> "Python mola"[1:4] 'yth' >>> "Python mola".find("mola")

    7 >>> "Python mola".replace("Python", "PHP no") 'PHP no mola'
  14. 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']
  15. 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"
  16. Usos  frecuentes:  dict >>> user = {'nick': 'neo', 'age': 24}

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

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

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

    >>> user.keys() ['nick', 'age'] >>> user.values() ['neo', 24] >>> user['age'] 24 >>> user.get('age', 20) 24 >>> 'nick' in user True >>> user.update({'nick': 'alatar', 'age': 25}) >>> user {'nick': 'alatar', 'age': 25}
  20. Usos  frecuentes:  str  % >>> "%s es muy sabio" %

    "Hycker" 'Hycker es muy sabio' >>> "%s sabe %i idiomas" % ("Hycker", 5) 'Hycker sabe 5 idiomas'
  21. Usos  frecuentes:  str  % >>> "%s es muy sabio" %

    "Hycker" 'Hycker es muy sabio' >>> "%s sabe %i idiomas" % ("Hycker", 5) 'Hycker sabe 5 idiomas' >>> t = "%(NOMBRE)s sabe %(IDIOMAS)i idiomas" >>> v = {'NOMBRE': 'Hycker', 'IDIOMAS': 5} >>> t % v 'Hycker sabe 5 idiomas'
  22. juego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py

    mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.py ... Módulos 1. Un  módulo  es  un  fichero  .py 2. Los  módulos  pueden   organizarse  en  paquetes. 3. Un  paquete  es  una  carpeta   que  con+ene  un  fichero  con   nombre  __init__.py
  23. juego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/ __init__.py

    mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.py ... Módulos 1. Un  módulo  es  un  fichero  .py 2. Los  módulos  pueden   organizarse  en  paquetes. 3. Un  paquete  es  una  carpeta   que  con+ene  un  fichero  con   nombre  __init__.py 1 2 3
  24. Módulos juego/ __init__.py bonus/ __init__.py estrella.py moneda.py planta.py ... personajes/

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

    __init__.py mario.py luigi.py princesa.py ... enemigos/ __init__.py seta.py tortuga.py bomba.py ... >>> from juego.personajes.mario import Mario >>> Mario() >>> from juego.personajes.mario import * >>> Mario() >>> from juego import personajes >>> personajes.mario.Mario()
  26. >>> from __future__ import braces File "<stdin>", line 1 SyntaxError:

    not a chance Identación 4  Espacios  para  la  identación
  27. >>> from __future__ import braces File "<stdin>", line 1 SyntaxError:

    not a chance Identación 4  Espacios  para  la  identación PEP 8
  28. •  Guido  van  Rossum  (2001) •  Recomendaciones  de  es0lo •

     “Readability  counts” •  “Code  is  read  much  more  oQen  than  it  is  wriSen.” •  Muy  recomendable  importante  seguirlo. PEP 8 ¿PEP  8?  h>p://www.python.org/dev/peps/pep-­‐0008/
  29. def my_first_function(p1, p2): return "Hello World!" 1 2 3 Funciones

    Minúsculas Palabras  separadas  por  _ Evitar  camelCase PEP 8
  30. Conversión  de  -pos >>> str(2) '2' >>> int(1.3) 1 >>>

    float(1) 1.0  h>p://docs.python.org/library/func-ons.html
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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
  40. 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']
  41. Funciones  de  ayuda >>> dir([1,2,3]) ['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',

    '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'] >>> help(filter) Help on built-in function filter in module __builtin__: filter(...) filter(function or None, sequence) -> list, tuple, or string Return those items of sequence for which function(item) is true. If function is None, return the items that are true. If sequence is a tuple or string, return the same type, else return a list. (END)
  42. class Student(object): def __init__(self, name, age): self.name = name self.age

    = age def hello(self): return 'My name is %s' % self.name Clases s = Student("Jorge", 24) camelCase
  43. class Student(object): def __init__(self, name, age): self.name = name self.age

    = age def hello(self): return 'My name is %s' % self.name 1 2 3 4 5 Clases s = Student("Jorge", 24) camelCase PEP 8
  44. El  operador  () • Es  importante  diferenciar: funcion    

     vs      funcion() Clase              vs        Clase() • El  operador  ()  permite: • Invocar  funciones: • Instanciar  clases: resultado = funcion() objeto = Clase("param1")
  45. $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
  46. $count = 0; while ($count < 5) { echo "Number

    ".$count; $count+=1; } count = 0 while count < 5: print "Number %i" % count count+=1 Sentencias:  while
  47. for ($i=0; $i < 5; $i++) { echo "Number ".$count;

    } for i in range(4): print "Number %i" % count Sentencias:  for
  48. try { $result = 3 / 0; } catch (Exception

    $e) { echo "Division by Zero" } try: result = 3 / 0 except: print "Division by Zero" Sentencias:  try-­‐except
  49. •  Python  es  un  lenguaje  fácil  de  aprender. •  Menos

     código: •  Muchos  Muchísimos  menos  errores  de  Sintaxis. •  Mayor  velocidad  de  escritura. •  Proto0pado...  U0lizado  por  grandes  empresas. Conclusiones
  50. •  Python  es  un  lenguaje  fácil  de  aprender. •  Menos

     código: •  Muchos  Muchísimos  menos  errores  de  Sintaxis. •  Mayor  velocidad  de  escritura. •  Proto0pado...  U0lizado  por  grandes  empresas. etc... Conclusiones
  51. Evolución  de  la  Web Desarrollo  Web 1ª  Generación 2ª  Generación

    3ª  Generación HTML CGI PHP ASP JSP ... Django Rails Symfony ...
  52. •  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
  53. •  Loose  coupling,    Acoplamiento  débil. •  Cada  capa  es

     independiente  y  desconoce  completamente     a  las  demás. •  Menos  código. •  Rápido  desarrollo. •  Esto  es  el  siglo  21,  todo  el  trabajo  tedioso  hay  que  evitarlo. •  Don’t  Repeat  Yourself  (DRY) Every distinct concept and/or piece of data should live in one, and only one, place. Redundancy is bad. Normalization is good.” “ Filoso\a
  54. •  Explicit  is  beSer  than  implicit. •  Este  es  un

     principio  de  Python. •  Django  no  debe  hacer  demasiada  “Magia”. •  Si  algo  es  “Mágico”  ha  de  haber  una  buena  razón. •  Consistencia •  Ha  de  ser  consistente  a  todos  los  niveles. •  Eficiencia,  Seguridad,  Flexibilidad  y  Simplicidad. Filoso\a  h>p://docs.djangoproject.com/en/dev/misc/design-­‐philosophies/
  55. *  Incluida  la  carpeta  del  proyecto Ficheros  y  Carpetas ¿Es

     Django  tán  simple  y  fácil  de  usar?
  56. *  Incluida  la  carpeta  del  proyecto Ficheros  y  Carpetas Ficheros

    Carpetas ¿Es  Django  tán  simple  y  fácil  de  usar?
  57. Rails Symfony 149 117 35 29 *  Incluida  la  carpeta

     del  proyecto Ficheros  y  Carpetas Ficheros Carpetas ¿Es  Django  tán  simple  y  fácil  de  usar?
  58. Rails Symfony 149 117 35 29 *  Incluida  la  carpeta

     del  proyecto Ficheros  y  Carpetas Ficheros Carpetas ¿Es  Django  tán  simple  y  fácil  de  usar?
  59. Rails Symfony 149 117 35 29 *  Incluida  la  carpeta

     del  proyecto Ficheros  y  Carpetas Django 5 2 Ficheros Carpetas ¿Es  Django  tán  simple  y  fácil  de  usar?
  60. Crear  nuestro  proyecto $ django-admin startproject dwitter -­‐  ¿Esto  es

     un  proyecto...  ?      Si  os  ve  mi  jefe... . !"" dwitter # !"" __init__.py # !"" settings.py # !"" urls.py # $"" wsgi.py $"" manage.py -­‐  Sí,  disponemos  de  un  proyecto  ‘funcional’  en  django. de  5  ficheros  ;-­‐)
  61. Arrancar  nuestro  proyecto de  5  ficheros  ;-­‐) $ cd dwitter

    $ python manage.py runserver Validating models... 0 errors found Django version 1.4, using settings 'dwitter.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
  62. Arrancar  nuestro  proyecto de  5  ficheros  ;-­‐) $ cd dwitter

    $ python manage.py runserver Validating models... 0 errors found Django version 1.4, using settings 'dwitter.settings' Development server is running at http://127.0.0.1:8000/ Quit the server with CONTROL-C.
  63. URLs  y  Vistas • El  fichero  urls.py  actúa  como  puerta

     de  entrada  para  las   pe0ciones  HTTP • Se  definen  URLs  elegantes  mediante  expresiones  regulares   que  redirigen  a  funciones  de  views.py urls.py views.py hSp://mysite.com/about/ html ... ¿urlpaSerns?
  64. URLs  y  Vistas • La  función  de  views.py  recibe  como

     parámetros  un  objeto   H>pRequest  y  todos  los  parámetros  de  la  URL  capturados,   teniendo  que  devolver  siempre  un  objeto  H>pResponse views.py H>pRequest(),  ... H>pResponse()
  65. URLs  y  Vistas Ejemplo  1:    http://mysite.com/time from django.conf.urls.defaults import

    * from mysite.views import hora_actual urlpatterns = patterns('', url(r'^time/$', hora_actual), ) from django.http import HttpResponse from datetime import datetime def hora_actual(request): now = datetime.now() html = "Son las %s." % now return HttpResponse(html) urls.py views.py
  66. URLs  y  Vistas from django.conf.urls.defaults import * from mysite.views import

    dentro_de urlpatterns = patterns('', url(r'^time/plus/(\d{1,2})/$', dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) urls.py views.py Ejemplo  2:    http://mysite.com/time/plus/2
  67. URLs  y  Vistas from django.conf.urls.defaults import * from mysite.views import

    dentro_de urlpatterns = patterns('', url(r'^time/plus/(\d{1,2})/$', dentro_de), ) from django.http import HttpResponse from datetime import datetime, timedelta def dentro_de(request, offset): offset = int(offset) dt = datetime.now() + timedelta(hours=offset) html = "En %i hora(s), serán las %s." % (offset, dt) return HttpResponse(html) urls.py views.py Ejemplo  2:    http://mysite.com/time/plus/2
  68. Templates • Separan  la  lógica  de  presentación  a  una  capa

     independiente. • Ficheros  independientes  (.html) • Lenguaje  independiente  (¡para  diseñadores!)
  69. Templates • Se  basan  en  dos  0pos  de  objetos:  Template()

     y  Context(). • Un  objeto  Template()  con0ene  el  string  de  salida  que   queremos  devolver  en  el  HSpResponse  (normalmente   HTML),  pero  incluyendo  e0quetas  especiales  de  Django. • Un  objeto  Context()  con0ene  un  diccionario  con  los   valores  que  dan  contexto  a  una  plan0lla,  los  que  deben   usarse  para  renderizar  un  objeto  Template(). "Bienvenido, {{ user }}." {'user': 'alatar'} Template: Context: "Bienvenido, alatar."
  70. Templates from django.http import HttpResponse from django.template import Template, Context

    from datetime import datetime PLANTILLA = """<html><body> Son las {{ hora }}. </body></html>""" def hora_actual(request): now = datetime.now() t = Template(PLANTILLA) c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) • Primera  aproximación  al  obje0vo:  Template  +  Context
  71. Templates • Segunda  aproximación  al  obje0vo:  open(),  read(),  close() from

    django.http import HttpResponse from django.template import Template, Context from datetime import datetime def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
  72. Templates • Segunda  aproximación  al  obje0vo:  open(),  read(),  close() from

    django.http import HttpResponse from django.template import Template, Context from datetime import datetime def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html)
  73. Templates • Segunda  aproximación  al  obje0vo:  open(),  read(),  close() from

    django.http import HttpResponse from django.template import Template, Context from datetime import datetime def hora_actual(request): now = datetime.now() fp = open('/home/django/templates/hora.html') t = Template(fp.read()) fp.close() c = Context({'hora': now}) html = t.render(c) return HttpResponse(html) Boring   boilerplate   code!
  74. Templates • Tercera  aproximación  al  obje0vo:  get_template() 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) TEMPLATE_DIRS = ( '/home/django/templates', ) seungs.py
  75. Templates • Tercera  aproximación  al  obje0vo:  get_template() TEMPLATE_DIRS = (

    '/home/django/templates', ) seungs.py 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)
  76. Templates • Tercera  aproximación  al  obje0vo:  get_template() TEMPLATE_DIRS = (

    '/home/django/templates', ) seungs.py 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) S0ll   boring...
  77. Templates • Obje0vo  alcanzado:  render() from django.shortcuts import render from

    datetime import datetime def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now})
  78. Templates • Obje0vo  alcanzado:  render() from django.shortcuts import render from

    datetime import datetime def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now}) Boring...?
  79. Templates • Obje0vo  alcanzado:  render() from django.shortcuts import render from

    datetime import datetime def hora_actual(request): now = datetime.now() return render(request, 'hora.html', {'hora': now}) AWESOME!
  80. 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
  81. 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.
  82. Templates:  {{}} <html> <head>Ejemplo templates</head> <body> Hola, {{ username }}.

    </body> </html> {'username': 'juan'} <html> <head>Ejemplo templates</head> <body> Hola, juan. </body> </html>
  83. Filters  y  Tags {{ varible|filter }} filter {% tag var1

    var2 %} inline  tag {% tag var1 %} ... {% endtag %} block  tag
  84. Templates:  tags  {%  %} {% comment %} Bu! {% endcomment

    %} comment for {% for elemento in lista %} <li>{{ elemento }}<li> {% endfor %}
  85. Templates:  tags  {%  %} {% comment %} Bu! {% endcomment

    %} comment for {% for elemento in lista %} <li>{{ elemento }}<li> {% endfor %} if {% if username == "Juan" %} Hola Juan, me gustas! {% else %} Hola {{ username }}, {% endif %} == != > < >= <= in and or not
  86. Templates:  tags  {%  %} cycle {% for elemento in lista

    %} <li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li> {% endfor %}
  87. Templates:  tags  {%  %} cycle {% for elemento in lista

    %} <li class="{% cycle 'rojo' 'azul' %}">{{ elemento }}<li> {% endfor %} include {% include "foo/bar.html" %}
  88. 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 %}
  89. 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 %}
  90. 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
  91. Templates:  Filters {'username': 'Juan es majo'} {{ username|length }} length

    12 {{ username|cut }} cut Juanesmajo {{ username|slugify }} slugify juan-es-majo
  92. Templates:  Filters {'username': 'Juan es majo'} {{ username|length }} length

    12 {{ username|cut }} cut Juanesmajo {{ username|slugify }} slugify juan-es-majo {{ username|wordcount }} wordcount 3
  93. 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
  94. 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
  95. Templates:  Filters {'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'} {{

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

    username|striptags }} striptags Juan es majo guapo y listo {{ username|truncatewords_html:4 }} truncatewords_html Juan es <b>majo guapo</b> ...
  97. Templates:  Filters {'username': 'Juan es <b>majo, guapo y <em>listo</em></b>'} {{

    username|striptags }} striptags Juan es majo guapo y listo {{ username|truncatewords_html:4 }} truncatewords_html Juan es <b>majo guapo</b> ... {{ username|removetags:”em a br” }} removetags Juan es <b>majo guapo y listo</b>
  98. 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
  99. 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
  100. 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
  101. Herencia  de  Templates base.html <html> <head> <title>Mi página personal</title> </head>

    <body> {% block content %} Contenido por defecto. {% endblock %} </body> </html> hija.html {% extends "base.html" %} {% block content %} Hola desde la portada. {% endblock %}
  102. Ejemplo  SQL def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret',

    host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names})
  103. Ejemplo  SQL def book_list(request): try: db = MySQLdb.connect(user='me', db='mydb', passwd='secret',

    host='localhost') cursor = db.cursor() cursor.execute('SELECT nama FROM books ORDER BY name') names = [] for row in cursor.fetchall() names.append(row[0]) db.close() except: return render_to_response('500.html') return render_to_response('book_list.html', {'names':names}) 1 2 3 4 5 6
  104. Modelo from django.db import models class Books(models.Model): name = models.CharField(blank=True,

    max_length=100) created = models.DateTimeField(blank=False) available = models.BooleanField(default=True) •  Independencia  SGBD! •  Definimos  estructuras  de  información  genéricas. •  Definimos  restricciones  (notnull,  blank,  max_lenght...) •  Única  definición  del  modelo  (configuración,  mapeo  a  db)  
  105. Modelo from django.db import models class Books(models.Model): name = models.CharField(blank=True,

    max_length=100) created = models.DateTimeField(blank=False) available = models.BooleanField(default=True) 2 1 3 4 5 6 •  Independencia  SGBD! •  Definimos  estructuras  de  información  genéricas. •  Definimos  restricciones  (notnull,  blank,  max_lenght...) •  Única  definición  del  modelo  (configuración,  mapeo  a  db)  
  106. 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
  107. 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
  108. ¿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;
  109. ¿Es  magia?  No. $ python manage.py sqlall website BEGIN; CREATE

    TABLE "website_books" ( "id" integer NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" datetime NOT NULL, "available" bool NOT NULL ); COMMIT; BEGIN; CREATE TABLE "website_books" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "created" timestamp with time zone NOT NULL, "available" boolean NOT NULL ); COMMIT;
  110. Configurar  sesngs.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', 'NAME':

    '', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } } 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
  111. Configurar  sesngs.py DATABASES = { 'default': { 'ENGINE': 'django.db.backends.', 'NAME':

    '', 'USER': '', 'PASSWORD': '', 'HOST': '', 'PORT': '', } } 1 2 3 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
  112. Creando  Tablas •  Crea  las  tablas  para  todos  los  modelos

     de  las  apps  instaladas   en  el  fichero  seungs.py •  No  actualiza  esquemas  si  la  tabla  existe. •  Eliminar  tabla  y  volver  a  ejecutar  syncdb
  113. Creando  Tablas $ python manage.py syncdb •  Crea  las  tablas

     para  todos  los  modelos  de  las  apps  instaladas   en  el  fichero  seungs.py •  No  actualiza  esquemas  si  la  tabla  existe. •  Eliminar  tabla  y  volver  a  ejecutar  syncdb
  114. syncdb $ python manage.py syncdb Creating table auth_permission Creating table

    auth_group Creating table auth_user Creating table auth_message Creating table django_content_type Creating table django_session Creating table django_site Creating table website_tweet You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (Leave blank to use 'neo'): admin E-mail address: [email protected] Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model Installing index for website.Tweet model
  115. syncdb $ python manage.py syncdb Creating table auth_permission Creating table

    auth_group Creating table auth_user Creating table auth_message Creating table django_content_type Creating table django_session Creating table django_site Creating table website_tweet You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (Leave blank to use 'neo'): admin E-mail address: [email protected] Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model Installing index for website.Tweet model django.contrib.auth
  116. syncdb $ python manage.py syncdb Creating table auth_permission Creating table

    auth_group Creating table auth_user Creating table auth_message Creating table django_content_type Creating table django_session Creating table django_site Creating table website_tweet You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (Leave blank to use 'neo'): admin E-mail address: [email protected] Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model Installing index for website.Tweet model website.tweet
  117. syncdb $ python manage.py syncdb Creating table auth_permission Creating table

    auth_group Creating table auth_user Creating table auth_message Creating table django_content_type Creating table django_session Creating table django_site Creating table website_tweet You just installed Django's auth system, which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username (Leave blank to use 'neo'): admin E-mail address: [email protected] Password: Password (again): Superuser created successfully. Installing index for auth.Permission model Installing index for auth.Message model Installing index for website.Tweet model django.contrib.auth
  118. 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()
  119. INSERT >>> p = Publisher.objects.create( ... name='O'Reilly', ... address='10 Fawcett

    St.', ... city='Cambridge', ... state_province='MA', ... country='U.S.A.', ... website='http://www.oreilly.com/') >>> p = Publisher( ... name='Apress', ... address='2855 Telegraph Avenue', ... city='Berkeley', ... state_province='CA', ... country='U.S.A.', ... website='http://www.apress.com/') >>> p.save() a) o = Model(...) o.save() manager.create(...) b)
  120. UPDATE >>> ... >>> p.id 52 >>> p.name = 'Apress

    Publishing' >>> p.save() o.save() 1
  121. UPDATE >>> Publisher.objects.all().update(country='USA') 2 >>> ... >>> p.id 52 >>>

    p.name = 'Apress Publishing' >>> p.save() o.save() queryset.update(...) 1 n
  122. DELETE >>> ps = Publisher.objects.all() >>> ps.delete() >>> ... >>>

    p.id 52 >>> p.delete() o.delete() queryset.delete() 1 n
  123. 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.
  124. 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.
  125. SELECT  de  N  resultados >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>]

    .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...)
  126. SELECT  de  N  resultados >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>]

    .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...) >>> Publisher.objects.exclude( country="U.S.A.", state_province="CA") [<Publisher: O'Reilly>] .exclude(...)
  127. SELECT  de  N  resultados >>> Publisher.objects.all() [<Publisher: Apress>, <Publisher: O'Reilly>]

    .all() >>> Publisher.objects.filter( country="U.S.A.", state_province="CA") [<Publisher: Apress>] .filter(...) >>> Publisher.objects.exclude( country="U.S.A.", state_province="CA") [<Publisher: O'Reilly>] .exclude(...) ¡Devuelven   QuerySets,  no   listas!
  128. get(),  filter()  y  exclude() Modelo.objects.filter(campo1="valor1", campo2="valor2") Los  parámetros  pueden  indicar

     mucho  más  que  igualdad  (=) campo__exact='' campo__iexact='' campo__contains='' campo__icontains='' campo__isnull=T|F campo__day=31 campo__gt=0 campo__gte=0 campo__lt=0 campo__lte=0 campo__in=[ ,] campo__month=12 campo__startswith='' campo__istartswith='' campo__endswith='' campo__iendswith='' campo__range=( ,) campo__year=2010
  129. ORDER  BY >>> Publisher.objects.order_by("name") [<Publisher: Apress>, <Publisher: O'Reilly>] .order_by(...) >>>

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

    Publisher.objects.order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] >>> Publisher.objects.order_by("-name", "country") [<Publisher: O'Reilly>, <Publisher: Apress>] Múl0ples  campos:
  131. ORDER  BY >>> Publisher.objects.order_by("name") [<Publisher: Apress>, <Publisher: O'Reilly>] .order_by(...) >>>

    Publisher.objects.order_by("-name") [<Publisher: O'Reilly>, <Publisher: Apress>] >>> Publisher.objects.order_by("-name", "country") [<Publisher: O'Reilly>, <Publisher: Apress>] Múl0ples  campos: ¡También   devuelve   QuerySets!
  132. Slicing >>> Publisher.objects.order_by("name")[0] <Publisher: Apress> [n:m] >>> Publisher.objects.order_by("name")[:2] [<Publisher: Apress>,

    <Publisher: O'Reilly>] >>> Publisher.objects.order_by("name")[1:2] [<Publisher: O'Reilly>] LIMIT
  133. Slicing >>> Publisher.objects.order_by("name")[0] <Publisher: Apress> [n:m] >>> Publisher.objects.order_by("name")[:2] [<Publisher: Apress>,

    <Publisher: O'Reilly>] >>> Publisher.objects.order_by("name")[1:2] [<Publisher: O'Reilly>] LIMIT OFFSET
  134. Related  Objects OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model):

    ... >>> c.motor <Motor: Motor object> ¿Cómo  usamos  la  relación  desde  las  instancias? Gracias  a  nosotros 1 1
  135. Related  Objects OneToOneField class Coche(models.Model): motor = OneToOneField(Motor) class Motor(models.Model):

    ... >>> c.motor <Motor: Motor object> >>> m.coche <Coche: Coche object> ¿Cómo  usamos  la  relación  desde  las  instancias? Gracias  a  nosotros Gracias  a  Django 1 1
  136. Related  Objects ForeignKeyField class Blog(models.Model): ... class Post(models.Model): blog =

    ForeignKeyField(Blog) >>> p.blog <Blog: Blog object> >>> b.post_set.all() [<Post: Post object>, ...] ¿Cómo  usamos  la  relación  desde  las  instancias? Gracias  a  nosotros Gracias  a  Django 1 n
  137. Related  Objects ManyToManyField class Post(models.Model): tags = ManyToManyField(Tag) class Tag(models.Model):

    ... >>> p.tags.add(t1, t2) >>> p.tags.all() [<Tag: Tag object>, ...] >>> t.post_set.add(p1, p2) >>> t.post_set.all() [<Post: Post object>, ...] ¿Cómo  usamos  la  relación  desde  las  instancias? Gracias  a  nosotros Gracias  a  Django n m
  138. Related  Objects En  todas  ellas  podemos  renombrar  el  puntero  inverso

    class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') 1 n
  139. Related  Objects En  todas  ellas  podemos  renombrar  el  puntero  inverso

    class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog: Blog object> >>> b.posts.all() [<Post: Post object>, ...] Gracias  a  nosotros Gracias  a  Django 1 n
  140. Related  Objects En  todas  ellas  podemos  renombrar  el  puntero  inverso

    class Blog(models.Model): ... class Post(models.Model): blog = ForeignKeyField(Blog, related_name='posts') >>> p.blog <Blog: Blog object> >>> b.posts.all() [<Post: Post object>, ...] Gracias  a  nosotros Gracias  a  Django 1 n Cuando  haya  2  relaciones  entre  2  modelos,  será  obligatorio
  141. 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'):
  142. Django  admin:  Instalación from django.conf.urls.defaults import * # Uncomment the

    next two lines to enable the admin: # from django.contrib import admin # admin.autodiscover() urlpatterns = patterns('', ... # url(r'^admin/', include(admin.site.urls)), ... ) 1 2 urls.py
  143. Django  admin:  Instalación from django.conf.urls.defaults import * # Uncomment the

    next two lines to enable the admin: from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', ... url(r'^admin/', include(admin.site.urls)), ... ) 1 2 urls.py
  144. Actualizando  la  BD $ python manage.py syncdb Creating table django_admin_log

    Installing index for admin.LogEntry model Admin  lista  para  usar
  145. admin.py • Cada  app  debe  de  tener  el  suyo. •

    Define  qué  modelos  serán  visibles  desde  el  admin  y   permite  personalizar  su  aspecto. from django.contrib import admin from website.models import Tweet class TweetAdmin(admin.ModelAdmin): list_display = ('id','user','message','timestamp') admin.site.register(Tweet, TweetAdmin)
  146. 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:
  147. 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 ...>
  148. Fixtures •  Es  muy  aburrido  crear  juegos  de  datos  cada

     vez  que  se   elimina  una  tabla  /  BD. •  No  nos  gustan  las  cosas  aburridas. •  Ficheros  (json/xml/yaml)  para  inicializar  una  Tabla. •  Pueden  crearse  una  vez  dispongamos  de  la  información: python manage.py dumpdata <appName appName appName.model ...> •  Se  cargan  u0lizando: python manage.py loaddata <fixture fixture ...> •  Si  se  llaman  ini<al_data  y  están  dentro  de  la  carpeta  fixtures   de  la  app,  se  cargan  al  ahcer  el  syncdb.
  149. Clases  involucradas Widget Componente  visual  equivalente  a  HTML TextInput CheckboxInput

    <input type='text'...> <input type='checkbox'...> Field Lógica  de  un  campo,  asociado  a  un  Widget EmailField IPAddressField widget, initial, error, ...
  150. Clases  involucradas Widget Componente  visual  equivalente  a  HTML TextInput CheckboxInput

    <input type='text'...> <input type='checkbox'...> Field Lógica  de  un  campo,  asociado  a  un  Widget EmailField IPAddressField widget, initial, error, ... Form Conjunto  de  Fields  de  un  formulario ContactForm [nombre, email, telefono, mensaje, ...]
  151. 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
  152. Creación  de  un  Form from django import forms class ContactForm(forms.Form):

    subject = forms.CharField(max_length=100, label='Topic') email = forms.EmailField(required=False) message = forms.CharField(widget=forms.Textarea) • Paso  1/3:  Definición  del  formulario  en  forms.py
  153. 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
  154. Creación  de  un  Form from django.shortcuts import render from mysite.contact.forms

    import ContactForm def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data send_mail(cd['subject'], cd['message'], ...) # ... return HttpResponseRedirect('/contact/thanks/') else: form = ContactForm() return render(request, 'contact_form.html', {'form': form}) • Paso  3/3:  Programación  de  la  vista  en  views.py
  155. Creación  de  un  Form from django.shortcuts import render from mysite.contact.forms

    import ContactForm def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data send_mail(cd['subject'], cd['message'], ...) # ... return HttpResponseRedirect('/contact/thanks/') else: form = ContactForm() return render(request, 'contact_form.html', {'form': form}) • Paso  3/3:  Programación  de  la  vista  en  views.py Pa_ern
  156. Creación  de  un  Form from django.shortcuts import render from mysite.contact.forms

    import ContactForm def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data send_mail(cd['subject'], cd['message'], ...) # ... return HttpResponseRedirect('/contact/thanks/') else: form = ContactForm() return render(request, 'contact_form.html', {'form': form}) • Paso  3/3:  Programación  de  la  vista  en  views.py Pa_ern
  157. Creación  de  un  Form from django.shortcuts import render from mysite.contact.forms

    import ContactForm def contact(request): if request.method == 'POST': form = ContactForm(request.POST) if form.is_valid(): cd = form.cleaned_data send_mail(cd['subject'], cd['message'], ...) # ... return HttpResponseRedirect('/contact/thanks/') else: form = ContactForm() return render(request, 'contact_form.html', {'form': form}) • Paso  3/3:  Programación  de  la  vista  en  views.py Pa_ern
  158. Validación  propia from django import forms class ContactForm(forms.Form): subject =

    forms.CharField(max_length=100) email = forms.EmailField(required=False) message = forms.CharField(widget=forms.Textarea) def clean_message(self): message = self.cleaned_data['message'] num_words = len(message.split()) if num_words < 4: raise forms.ValidationError("Not enough words!") return message Podemos  programar  validación  extra  asociada  a  cada  Field   del  formulario  escribiendo  un  método  clean_<fieldname>:
  159. Validación  propia from django import forms class ContactForm(forms.Form): subject =

    forms.CharField(max_length=100) email = forms.EmailField(required=False) message = forms.CharField(widget=forms.Textarea) def clean_message(self): message = self.cleaned_data['message'] num_words = len(message.split()) if num_words < 4: raise forms.ValidationError("Not enough words!") return message Podemos  programar  validación  extra  asociada  a  cada  Field   del  formulario  escribiendo  un  método  clean_<fieldname>:
  160. 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:
  161. Forms  a  par-r  de  Models from django.db import models class

    Author(models.Model): name = models.CharField(max_length=100) birth_date = models.DateField(blank=True, null=True) country = models.ModelChoiceField(Country) ... from django import forms from books.models import Author class AuthorForm(forms.ModelForm): class Meta: model = Author exclude = ('country',) models.py forms.py
  162. Views  avanzadas Generic  Views Vistas  con  funcionalidad  genérica  parametrizable  

    mediante  un  diccionario  de  Extra  Op-ons from django.conf.urls.defaults import * from mysite import views urlpatterns = patterns('', url(r'^foo/$', views.foobar_view, {'template_name': 'template1.html'}), url(r'^bar/$', views.foobar_view, {'template_name': 'template2.html'}), ) Las  tuplas  de  pa>erns()  pueden  tener  3  elementos
  163. Views  avanzadas Renderiza  directamente  la  template  indicada from django.conf.urls.defaults import

    * from django.views.generic.simple import direct_to_template urlpatterns = patterns('', url(r'^about/$', direct_to_template, {'template': 'about.html'}) ) from django.views.generic.simple import direct_to_template Es  la  Generic  View  más  simple  y  más  u+lizada
  164. Template  Library Nos  permite  extender  el  sistema  de  templates  

    de  Django  con  Filters  y  Tags  propios Uso {% load milibreria %} ... {{ variable|mifiltro:"param" }} ... {% mitag param1 param2 %}
  165. Template  Library Nos  permite  extender  el  sistema  de  templates  

    de  Django  con  Filters  y  Tags  propios Uso {% load milibreria %} ... {{ variable|mifiltro:"param" }} ... {% mitag param1 param2 %} Creación
  166. Custom  Filters Un  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.
  167. Custom  Filters Un  Filter  es  una  función  Python  que: •

    Recibe  1  o  2  argumentos:  (value  [,  arg]). • Siempre  devuelve  algo:  el  resultado,  value  o  "". • Falla  silenciosamente:  no  lanza  excepciones. from django import template register = template.Library() def cut(value, arg=' '): return value.replace(arg, '') register.filter('cut', cut) Ejemplo
  168. Custom  Filters Un  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, '')
  169. Python   2.4  se  hizo   sexy Custom  Filters Un

     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, '')
  170. Custom  Tags El  método  genérico  para  crear  Tags  es  complejo.

    Vamos  a  ver  cómo  crear  los  2  +pos  de  Tags  más  sencillos: SimpleTags InclusionTags • Son  inline • Reciben  1  argumento • Devuelven  un  string • Son  inline • Reciben  n  argumentos • Devuelven  un  diccionario • Insertan  su  propio   fragmento  de  template
  171. SimpleTags Ejemplo:  Devolver  la  hora  actual  formateada. {% current_time "%Y-%m-%d

    %I:%M %p" %} from django import template register = template.Library() @register.simple_tag def current_time(format): try: return datetime.datetime.now().strftime(str(format)) except UnicodeEncodeError: return ''
  172. InclusionTags Ejemplo:  Mostar  anuncios  si  el  usuario  no  es  premium.

    {% show_adverts user %} {% for advert in adverts %} <img src='{{ advert.image }}' /> {% endfor %} adverts.html milibreria.py
  173. InclusionTags Ejemplo:  Mostar  anuncios  si  el  usuario  no  es  premium.

    @register.inclusion_tag('website/adverts.html') def show_adverts(user): adverts = [] if not user.profile.is_premium: adverts = Advert.objects.order_by('?').limit(5) return {'adverts': adverts} {% show_adverts user %} {% for advert in adverts %} <img src='{{ advert.image }}' /> {% endfor %} adverts.html milibreria.py
  174. Middleware class 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.""" # ...
  175. Middleware Tenemos  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', )
  176. Middleware 1. Sistema  de  BETA 1. Nos  aseguramos  de  controlar

     todas  páginas. 2. Si  el  usuario  +ene  una  IP  o  un  User  o... 2. Si6o  en  Mantenimiento 1. Todo  el  Site  muestra  un  splash  excepto... 3. Cache  Middleware 1. Si  la  vista  cumple  un  patrón  (User  no  logeado,...)   cacheamos  la  página. 4.  etc...
  177. Ofrece  integración  con  la  librería  GNU  ge>ext  de  i18n 1.

    Un  fichero  .pot  con+ene  todos  los  strings  usados contabilidad.pot 2. En  cada  fichero  .po  se  guarda  una  traducción es_ES.pot      es_AR.pot      en_GB.pot 3. Cada  .po  se  compila  y  genera  un  .mo  binario es_ES.mo      es_AR.mo      en_GB.mo Internacionalización
  178. Internacionalización from django.utils.translation import ugettext as _ print _("Cadena de

    texto") • ¿Cómo  indicar  qué  strings  deben  ser  traducidos? • Ges+ón  cómoda  de  singulares  y  plurales
  179. Internacionalización from django.utils.translation import ugettext as _ print _("Cadena de

    texto") • ¿Cómo  indicar  qué  strings  deben  ser  traducidos? from django.utils.translation import ungettext frase = ungettext("Hay %(total)d resultado", "Hay %(total)d resultados", total) % { 'total': total } • Ges+ón  cómoda  de  singulares  y  plurales
  180. caching •Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache! •Recomendado  =

     memcached •Acceder  a  la  BD  es  caro,  muy  caro. •El  Hardware  es  “gra0s”  en  comparación  con  op0mizar  código  op0mizado. •Ejemplo  (Facebook):
  181. caching •Si  queremos  escalar  nuestro  proyecto  rápidamente....  Cache! •Recomendado  =

     memcached •Acceder  a  la  BD  es  caro,  muy  caro. •El  Hardware  es  “gra0s”  en  comparación  con  op0mizar  código  op0mizado. •Ejemplo  (Facebook): 300+Tb  Memcached
  182. caching from django.views.decorators.cache import cache_page @cache_page(60 * 15) def my_view(request):

    ... views {% load cache %} {% cache 500 sidebar %} .. sidebar .. {% endcache %} templates
  183. caching low  level >>> from django.core.cache import cache >>> cache.set('my_key',

    'hello, world!', 30) >>> cache.get('my_key') 'hello, world!' •Podemos  cachear  cualquier  0po  de  objeto  que  se  pueda  serializar. •  QuerySets •  Listas •  ...
  184. Virtualenv •Independencia  completa  de  las  librerías  del  sitema. •Cada  proyecto

     0ene  su  juego  de  librerías  en  la  versión  que  necesita •Sin  miedo  a  actualizar •Sin  miedo  a  migrar •etc...
  185. Virtualenv •Independencia  completa  de  las  librerías  del  sitema. •Cada  proyecto

     0ene  su  juego  de  librerías  en  la  versión  que  necesita •Sin  miedo  a  actualizar •Sin  miedo  a  migrar •etc... $ virtualenv mi_entorno crear
  186. Virtualenv •Independencia  completa  de  las  librerías  del  sitema. •Cada  proyecto

     0ene  su  juego  de  librerías  en  la  versión  que  necesita •Sin  miedo  a  actualizar •Sin  miedo  a  migrar •etc... $ virtualenv mi_entorno crear $ source mi_entorno/bin/activate ac-var
  187. PIP •Gestor  de  paquetes  del  siglo  21  :D •Permite  especificar

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

     un  fichero  de  REQUIREMENTS  con  un  listado  de   paquetes  a  instalar. Django==1.4 psycopg2 feedparser==4.1 stripogram==1.5 GChartWrapper==0.8 pip install -E mi_entorno -r REQUIREMENTS
  189. nginx  +  Gunicorn nginx gunicorn •  nginx  [engine  x]  is

     a  HTTP  and  reverse  proxy  server. •  Con  una  configuración  muy  sencilla  podremos  u0lizarlo  como  proxy   inverso  a  gunicorn. •  hSp://gunicorn.org/ •  Servidor  Web  WSGI  implementado  en  Python •  Facilidades  de  puesta  en  marcha  de  proyectos  django •  Fácilmente  configurable  usando  nginx •  hSp://nginx.org/
  190. gunicorn Django nginx  :80 web1 gunicorn Django nginx  :80 web2

    gunicorn Django nginx  :80 webn nginx  :80  :443 varnish haproxy frontend1 nginx  :80  :443 varnish haproxy frontend2 ipfailover Deploy no  tan  sencillo
  191. Repe00on  leads  to  boredom, boredom  to  horrifying  mistakes, horrifying  mistakes

     to  God-­‐I-­‐wish-­‐I-­‐was-­‐s0ll-­‐bored. “
  192. Magia  avanzada 1. Views  avanzadas 2. Context  Processors 3. Custom

     Template  Filters  &  Tags 4. Middleware 5. Internacionalización 6. Caching 7. Despliegue 8. Apps  recomendadas
  193. django-­‐south •  Sistema  inteligente  para  realizar  de  manera  automá0ca  migraciones

      de  esquemas. •¿Que  sucede  si  tengo  un  Modelo  con  100.000  filas  y  quiero  añadir   una  columna?  ...  south! •Necesito  migrar  el  contenido  desde  mi  an0guo  Modelo  a  uno   nuevo...  south! •Necesito  que  ...  south! hSp://south.aeracode.org/
  194. django-­‐south $ python manage.py schemamigration website --initial crear  primer  schema

    $ python manage.py schemamigration website --auto crear  2-­‐*  migración $ python manage.py migrate aplicar  migraciones
  195. django-­‐south hSp://south.aeracode.org/ $ python manage.py schemamigration website --initial crear  primer

     schema $ python manage.py schemamigration website --auto crear  2-­‐*  migración $ python manage.py migrate aplicar  migraciones
  196. django-­‐haystack •  “EL”  Sistema  de  búsquedas  para  Django •  Funciona

     con  varios  sistemas  de  Indexación •  Solr,  Xapian,  Whoosh •  Features: •  ‘More  like  this’ •Face0ng •Highligh0ng •  Spelling  Sugges0on •  etc...  h>p://haystacksearch.org
  197. django-­‐registra-on •Sistema  completo  para  la  ges0ón  de  usuarios. •Desde  el

     registro,  ac0vación  etc... •DRY!! •Instalación  muy  sencilla.  h>p://bitbucket.org/ubernostrum/django-­‐registra-on/
  198. django-­‐registra-on /ac0vate/complete/ /ac0vate/<ac0va0on_key>/ /  register/ /  register/complete/ /  register/closed/ /

     login/ /  logout/ /  password/change/ /  password/change/done/ /  password/reset/ /  password/reset/confirm/<token> /  password/reset/complete/ /  password/reset/done/ /  reac0vate/  h>p://bitbucket.org/ubernostrum/django-­‐registra-on/
  199. •Sistema  de  Tareas  Asíncronas  distribuidas. •Features:  Colas,  Concurrencia,  Distribuido... •Muy

     fácil  implementación  y  escalable. •Casos  prác-cos: •Enviar  un  email •Calcular  el  karma  de  de  los  usuarios  del  sistema. •Tareas  programadas  (Limpieza,  Post-­‐procesado,  etc...) Celery  h>p://celeryproject.org
  200. from celery.decorators import task @task def add(x, y): return x

    + y >>> result = add.delay(4, 4) >>> result.wait() # wait for and return the result 8 Celery  h>p://celeryproject.org
  201. from celery.decorators import task @task def add(x, y): return x

    + y >>> result = add.delay(4, 4) >>> result.wait() # wait for and return the result 8 • Las  Task  son  simples  funciones  (O  class  si  queremos) • Python  100%  el  retorno  será  el  resultado • Usamos  el  decorador  @task  para  registrarla • El  método  .delay  sobre  cualquier  Task  lo   ejecuta  en  background. • Podemos  esperar  a  que  un  Worker  ejecute   la  tarea  o  seguir  haciendo  otras  acciones. Celery  h>p://celeryproject.org