Curso de Django | Django Course

  • 2,361 views
Uploaded on

Django course given while working at Except. In spanish.

Django course given while working at Except. In spanish.

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
No Downloads

Views

Total Views
2,361
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
74
Comments
1
Likes
2

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. django el curso Día 3
  • 2.
    • Vistas
        • Patrones de vistas
        • HttpResponse objects
    • Plantillas
        • lenguaje
        • RequestContext y Contextos
    • Managers
        • agregar funcionalidad
        • modificar queryset inicial
    • AJAX y Serialización
    Temario
  • 3. Vistas
      • Una función “callback” en python asociada a un url.
      • Siempre devuelven una instancia HttpResponse o una subclase de HttpResponse.
      • Respuesta puede ser: contenidos html, redirección, 404, xml, etc.
      • Pueden “vivir” en cualquier lado, pero tienen que estar en el PythonPath.
  • 4. # en urls.py (r'^example/project/(?P<project_id>d+)/$', 'example_get_project') # en views.py def example_get_project (request, project_id): try: p = Project.objects.get(project__pk=project_id) # pk synonym of id html = ( &quot;<html> <body>&quot; &quot;<p> Project Name: %s </p>&quot; &quot;<p> Project Description: %s </p>&quot; &quot;</body> </html>&quot; ) % (p.name, p.description) except Project.DoesNotExist: html = &quot;<html> <body> <p> <b> Bu! :-( No existe! <b> <p> </body> <html>&quot; return HttpResponse(html) Vistas
  • 5. from django.http import HttpResponse, HttpResponseNotFound def example_get_project (request, project_id): try : p = Project.objects.get(project__pk=project_id) # pk synonym of id html = ( &quot;<html> <body>&quot; &quot;<p> Project Name: %s </p>&quot; &quot;<p> Project Description: %s </p>&quot; &quot;</body> </html>&quot; ) % (p.name, p.description) return HttpResponse(html) except Project.DoesNotExist: html = &quot;<html> <body> <p> <b>&quot; &quot;Bu! :-( No existe!&quot; &quot;<b> <p> </body> <html>&quot; return HttpResponseNotFound(html ) Vistas
  • 6. from django.http import HttpResponse, Http404 def example_get_project (request, project_id): try : p = Project.objects.get(project__pk=project_id) # pk synonym of id html = ( &quot;<html> <body>&quot; &quot;<p> Project Name: %s </p>&quot; &quot;<p> Project Description: %s </p>&quot; &quot;</body> </html>&quot; ) % (p.name, p.description) return HttpResponse(html) except Project.DoesNotExist: raise Http404
      • 404 común, buena idea tener una página de error estándar.
    Vistas
  • 7. def example_get_project_with_template (request, project_id): try : p = Project.objects.get(pk=project_id) t = loader.get_template('project_details.html') c = Context({'project': p}) r = HttpResponse(t.render(c), mimetype=&quot;application/xhtml+xml&quot;) return r except Project.DoesNotExist: raise Http404 def example_get_project_with_get_object (request, project_id) p = get_object_or_404(Project, pk=project_id) return render_to_response('project_details', { 'project' : p })
      • funciones que se extienden a través de varias capas
      • utilizando plantillas
    Vistas
  • 8.
      • Es la responsabilidad del programador devolver en cada vista un HttpResponse.
    Vistas
      • Se puede utilizar como un archivo...
    In [1]: from django.http import HttpResponse In [2]: response = HttpResponse() In [3]: response.write(&quot;<p>Here's the text of the Web page.</p>&quot;)
      • Se pueden modificar los headers...
    In [5]: response['X-DJANGO'] = 'It is the best' In [6]: response['X-DJANGO'] Out[6]: 'It is the best'
      • Se pueden pasar iteradores, que devuelvan strings. Si se inicializo con un iterador, no se puede usar como un archivo.
  • 9. import csv, StringIO def _gen(qset): io = StringIO.StringIO() writer = csv.writer(io) writer.writerow(TaskLog.header_row) # Add header yield io.getvalue() for item in qset: io = StringIO.StringIO() writer = csv.writer(io) writer.writerow(item.get_csv_row()) yield io.getvalue() return def csv_log(request, project_id, username): ... response = HttpResponse(_gen(queryset), mimetype='text/csv') response[ 'Content-Disposition' ] = ( 'attachment; filename=' 'tasklogs' '-for-%s.csv' ) % username return response
  • 10. Atributos HttpResponse.content Métodos HttpResponse.__init__(content='', mimetype=None, status=200, content_type=DEFAULT_CONTENT_TYPE) HttpResponse.__setitem__(header, value) HttpResponse.__delitem__(header) HttpResponse.__getitem__(header) HttpResponse.has_header(header) HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None) HttpResponse.delete_cookie(key, path='/', domain=None) HttpResponse.write(content) HttpResponse.flush() HttpResponse.tell()
  • 11. class HttpResponseRedirect class HttpResponsePermanentRedirect class HttpResponseNotModified class HttpResponseBadRequest class HttpResponseNotFound class HttpResponseForbidden class HttpResponseNotAllowed class HttpResponseGone class HttpResponseServerError
  • 12. Vistas
      • Ejercicio: crear una vista que devuelva un CSV con cuantas horas hizo cada usuario por tarea. Algo así: 'Usuario', 'Tarea', 'Horas'
  • 13. Plantillas
    • Documento de texto (python string) del cual podemos generar HTML, CSV, XML, ú otros formatos de texto.
    • Lenguaje, con variables, etiquetas (tags) y filtros (filters)
    • variables son remplazadas por valores
    • las etiquetas nos permiten controlar la logica de las plantillas
    • filtros permiten modificar el valor de las variables
  • 14. In [1]: from django.template import Template # Parsear código de Templates y generar una instancia In [4]: t = Template(&quot;Hello, {{ name }}&quot;) In [6]: print t <django.template.Template object at 0x87c7aec> In [8]: from django.template import Context # Una vez compilada podemos renderizar con un contexto In [9]: c = Context({'name' : 'World'}) In [10]: t.render(c) Out[10]: u'Hello, World' Plantillas
  • 15. {% extends &quot;base_for_examples.html&quot; %} {% block title %} Un proyecto: {{ project.name }} {% endblock title %} {% block content %} <p> <b> Un proyecto: </b> </p> <hr/> <p> Nombre: {{ project.name|upper }} </p> <p> Descripción: {{ project.description|truncatewords:&quot;10&quot; }} </p> {% endblock content %} Variable, el punto (.) se accede a los atributos de la variable, diccionario, llamada a una función sin arg. Etiqueta que define un bloque que se puede sobre escribir. Herencia. Filtro, módifica el string, letras mayúsculas Indica de que template hereda Plantillas TEMPLATE_STRING_IF_INVALID
  • 16. In [1]: from django.template import Template, Context In [12]: b = { 'apellido' :'Perez', 'ocupacion' : 'astronauta' } In [13]: t = Template('Yo me llamo {{ dict.apellido }} y soy {{ dict.ocupacion }}') In [14]: c = Context({'dict' : b}) In [15]: t.render(c) Out[15]: u'Yo me llamo Perez y soy astronauta' In [16]: t = Template('Yo me llamo {{ dict.apellido|upper }} y soy {{ dict.ocupacion }}') In [17]: t.render(c) Out[17]: u'Yo me llamo PEREZ y soy astronauta'
    • Varios filtros definidos, y se pueden definir propios
    Plantillas
  • 17. Plantillas
    • add {{ value|add:&quot;2&quot; }}
    • cut
    • default
    • escape
    • floatformat 34.23234,{{ value|floatformat }},34.2
    • length
    • safe
    • slugify
  • 18. {% if project_list %} {% for project in project_list %} <li> <a class=&quot;head&quot; href='#'>{{project.name}}</a> <ul> {% for task in project.task_set.all %} <li> <a href=&quot;#&quot; onclick=&quot;retrieve_tasklogs({{ task.id }})&quot;> {{ task.name }} </a> </li> {% endfor %} </ul> </li> {% endfor %} {% else %} <li> <a class=&quot;head&quot; href='#'> No projects in database </a> Please add some projects in the database </li> {% endif %} Plantillas
  • 19.
    • {% cycle 'row1' 'row2' %}
    • {% autoescape off %} {{ whatever }} {% autoescape %}
    • {# comment #}
    • {% ifequal user.id comment.user_id %} .. {% endifequal %}
    • {% include &quot;foo/bar.html&quot; %}
    • {% load %}
    • {% url path.to.some_view arg1,arg2,name1=value1 %}
    • {% with %}
    • http://docs.djangoproject.com/en/dev/ref/templates/builtins/
    Plantillas
  • 20. <!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;> <html> <head> {% block title %} Titulo {% endblock title %} </head> <body> {% block content %} Aquí el contenido de la página {% endblock content %} </body> </html> Plantillas
    • Herencia / Extensión
  • 21. {% extends &quot;base_for_examples.html&quot; %} {% block title %} Un proyecto: {{ project.name }} {% endblock title %} {% block content %} {% block.super %} <p> <b> Un proyecto: </b> </p> <hr/> <p> Nombre: {{ project.name|upper }} </p> <p> Descripción: {{ project.description|truncatewords:&quot;10&quot; }} </p> {% endblock content %} Plantillas
  • 22. <!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.01 Transitional//EN&quot; &quot;http://www.w3.org/TR/html4/loose.dtd&quot;> <html> <head> <title> Un proyecto: Curso Django </title> </head> <body> Pagina de la Aplicación: TimeTracker <p> <b> Un proyecto: </b> </p> <hr/> <p> Nombre: CURSO DJANGO </p> <p> Descripción: curso, curso, curse! </p> </body> </html> Plantillas
    • http://localhost:8000/timetracker/example/project-with-shortcuts/1/
  • 23. Plantillas
      • Contextos
    In [23]: c = Context() In [24]: c['foo'] = 'first level' In [25]: c.push() Out[25]: {} In [26]: c['foo'] = 'second level' In [27]: c['foo'] Out[27]: 'second level' In [28]: c Out[28]: [{'foo': 'second level'}, {'foo': 'first level'}] In [29]: c.pop() Out[29]: {'foo': 'second level'} In [30]: c['foo'] Out[30]: 'first level' In [31]: c.pop() ----------------------------------------------------- <class 'django.template.context.ContextPopException'>
  • 24. Plantillas
      • RequestContext (subclase de Context)
        • Toma como un argumento Request
        • Agrega variables al contexto según los “Preprocesadores del Contexto” indicados por TEMPLATE_CONTEXT_PROCESSORS.
        • Se le pueden agregar preprocesadores al instanciarlos
    def ip_address_processor(request): return {'ip_address': request.META['REMOTE_ADDR']} def some_view(request): # ... c = RequestContext(request, {'foo': 'bar',}, [ip_address_processor]) return t.render(c)
  • 25. Plantillas
    • django.core.context_processors.auth
      • Agrega permisos {{perms}}, usuario {{ user }}
    • django.core.context_processors.debug
      • Información de Debug {{ sql_queries }}, {{ debug }}
    • django.core.context_processors.i18n
      • {{ LANGUAGES }}, {{ LANGUAGE_CODE }}
    • django.core.context_processors.media
    • django.core.context_processors.request
    • crear un propio:
      • función python, toma un argumento, devuelve un dict
  • 26. Plantillas TEMPLATE_CONTEXT_PROCESSORS = ( &quot;django.core.context_processors.auth&quot;, &quot;django.core.context_processors.debug&quot;, &quot;django.core.context_processors.i18n&quot;, &quot;django.core.context_processors.media&quot;, &quot;timetracker.views.add_next_url&quot;, ) # --- request preprocessor / en views def add_next_url (request): return { 'next_url' : request.GET.get('next', None) }
      • Ejemplo
  • 27. def some_view(request): # ... return render_to_response( 'my_template.html', my_data_dictionary, context_instance=RequestContext(request) ) Plantillas
      • Pasando un instancia de contexto
  • 28. Plantillas
      • Ejercicio: Crear vistas y plantillas para ver los detalles de un proyecto. Los proyectos se deben listar como tabla y cada se deben diferenciar las filas impares de las pares con algún color.
  • 29. Managers
    • Interfaz que provee las operaciones de consulta a la base de datos
    In [1]: from timetracker.models import Project In [2]: Project.objects.all() Out[2]: [<Project: Curso Django>, <Project: Eff>] In [5]: Project.objects.filter(name='Curso Django') Out[5]: [<Project: Curso Django>]
  • 30. Managers
    • objects puede ser renombrado en cada modelo
    from django.db import models class TimeTrackerBaseModel (models.Model): ... class Task (TimeTrackerBaseModel): ... tasks = models.Manager() In [7]: from timetracker.models import Task In [8]: Task.objects.all() ... <type 'exceptions.AttributeError'>: type object 'Task' has no attribute 'objects' In [9]: Task.tasks.all() Out[9]: [<Task: edit templates, test and fix views>, <Task: crear algunas vistas>]
  • 31. Managers
    • Se pueden usar Manager modificados extendiendo la clase Manager é instanciando en el modelo.
    • Nota: Es el método sugerido para agregar funcionalidad a nivel de las tablas.
    • Agregar nuevos métodos.
    • Modificar el QuerySet inicial de los Managers
  • 32. Managers
    • Agregar nuevos métodos.
    class TaskManager (models.Manager): def admin_task_count( self ): from django.db import connection cursor = connection.cursor() cursor.execute( &quot;&quot;&quot; SELECT COUNT(*) FROM timetracker_task WHERE timetracker_task.owner_id = 1; &quot;&quot;&quot; ) return cursor.fetchall()[0][0] def query_admin_task_count( self ): return self .filter(owner__username='admin').count() class Task (TimeTrackerBaseModel): ... tasks = TaskManager()
  • 33. Managers
    • Agregar nuevos métodos.
    In [2]: from timetracker.models import Task In [3]: Task.tasks.all() Out[3]: [<Task: edit templates, test and fix views>, <Task: crear algunas vistas>] In [4]: Task.tasks.admin_task_count() Out[4]: 2 In [5]: Task.tasks.query_admin_task_count() Out[5]: 2
  • 34. Managers class UncompletedTaskManager (models.Manager): def get_query_set(self): return super (UncompletedTaskManager, self ) .get_query_set().exclude(state=30) class CompletedTaskManager (models.Manager): def get_query_set(self): return super (CompletedTaskManager, self ) .get_query_set().filter(state=30) # Importante el primer Manager que Django encuentra es el # default class Task (TimeTrackerBaseModel): ... tasks = TaskManager() uncompleted_tasks = UncompletedTaskManager() completed_tasks = CompletedTaskManager()
      • Modificar el QuerySet inicial de los Managers
  • 35. Managers In [1]: from timetracker.models import Task In [2]: Task.uncompleted_tasks.all() Out[2]: [<Task: crear algunas vistas>] In [3]: Task.completed_tasks.all() Out[3]: [<Task: edit templates, test and fix views>] In [4]: Task.tasks.all() Out[4]: [<Task: edit templates, test and fix views>, <Task: crear algunas vistas>]
      • Modificar el QuerySet inicial de los Managers
      • Ejercicio: crear/editar un Manager con una función que devuelve el promedio de horas para cada usuario
  • 36. Managers
      • Managers que estén definidos en clases no abstractas no se heredan. Se supone que en general los managers son particulares para la clase.
      • Managers definidos en una clase abstracta se heredan.
      • El default Manager es el primero que está definido en la clase, si no, el primero en la clase abstracta, si no Django genera uno.
      • use_for_related_fields = True , dentro de la clase del Manager, indica que use el Manager para obj. relacionados.
  • 37. Un poco de AJAX y un poco de Serialización
  • 38. AJAX
    • Utilizamos un framework: jQuery
    • Asynchronous Javascript and XML
    • urlpatterns += patterns('', (r'^resources/(?P<path>.*)$', 'django.views.static.serve', dict(document_root=media_root, show_indexes=True)), )
    • Necesitamos servir javascript.
  • 39. AJAX
    • Ejemplo: buscar html generado por una vista
    {% block script %} function get_project_tasks(url) { $.ajax({ type: &quot;GET&quot;, url: url, dataType: &quot;html&quot;, success: function(html){ $(&quot;#id_tasks_set&quot;).empty().append(html); } }); } {% endblock script %} <!-- En la platilla base --> <script type=&quot;text/javascript&quot; src=&quot;/timetracker/resources/js/jquery.js&quot;> </script>
  • 40. AJAX def example_ajax_get_task_for_project (request, project_id): if request.method == 'GET': p = get_object_or_404(Project, pk=project_id) tasks = p.task_set.all() if request.is_ajax(): # HTTP_X_REQUESTED_WITH # with string 'XMLHttpRequest' return render_to_response('task_details_ajax.html', { 'tasks' : tasks }) else: return render_to_response('project_with_tasks_details.html', { 'project' : p, 'tasks' : tasks }) <!-- La plantilla --> <ul> {% for task in tasks %} <li> Nombre: {{ task.name }} </li> <li> Descripción: {{ task.description }} </li> <li> Fecha de Inicio: {{ task.start_date }} </li> <!-- plin, plin, plin .. --> {% endfor %} <ul>
  • 41. Serialización In [11]: from django.core import serializers In [12]: data=serializers.serialize(&quot;xml&quot;,Project.objects.filter(pk=1), fields=('name',)) In [17]: data Out[17]: '<?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?> <django-objects version=&quot;1.0&quot;><object pk=&quot;1&quot; model=&quot;timetracker.project&quot;><field type=&quot;CharField&quot; name=&quot;name&quot;>Curso Django</field></object></django-objects> In [18]: for obj in serializers.deserialize(&quot;xml&quot;, data): ....: print obj, type(obj) ....: ....: <DeserializedObject: Curso Django> <class 'django.core.serializers.base.DeserializedObject'>
  • 42. Serialización
    • se pueden salvar objetos 'deserializados'
    • se puede serializar a un archivo
    • se pueden instanciar...
    out = open(&quot;file.xml&quot;, &quot;w&quot;) xml_serializer.serialize(SomeModel.objects.all(), stream=out) XMLSerializer = serializers.get_serializer(&quot;xml&quot;) xml_serializer = XMLSerializer() xml_serializer.serialize(queryset) data = xml_serializer.getvalue() for deserialized_object in serializers.deserialize(&quot;xml&quot;, data): if object_should_be_saved(deserialized_object): deserialized_object.save()
  • 43. AJAX y Serialización
      • Ejercicio: crear una vista serialize los TaskLog y los muestre cada vez que se pidan utilizando AJAX
    json_serializer = serializers.get_serializer(&quot;json&quot;)() json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
  • 44. This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 2.5 Argentina License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/2.5/ar/ or send a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.