Curso de Django | Django Course

download Curso de Django | Django Course

If you can't read please download the document

Transcript of Curso de Django | Django Course

django

el curso

Da 3

Vistas

Patrones de vistas

HttpResponse objects

Plantillas

lenguaje

RequestContext y Contextos

Managers

agregar funcionalidad

modificar queryset inicial

AJAX y Serializacin

Temario

Vistas

Una funcin callback en python asociada a un url.

Siempre devuelven una instancia HttpResponse o una subclase de HttpResponse.

Respuesta puede ser: contenidos html, redireccin, 404, xml, etc.

Pueden vivir en cualquier lado, pero tienen que estar en el PythonPath.

# en urls.py(r'^example/project/(?P\d+)/$', 'example_get_project')

# en views.pydef example_get_project (request, project_id): try: p = Project.objects.get(project__pk=project_id) # pk synonym of id html = (" " " Project Name: %s " " Project Description: %s " " ") % (p.name, p.description) except Project.DoesNotExist: html = " Bu! :-( No existe! " return HttpResponse(html)Vistasfrom django.http import HttpResponse, HttpResponseNotFounddef example_get_project (request, project_id): try: p = Project.objects.get(project__pk=project_id) # pk synonym of id html = (" " " Project Name: %s " " Project Description: %s " " ") % (p.name, p.description) return HttpResponse(html) except Project.DoesNotExist: html = " " "Bu! :-( No existe!" " " return HttpResponseNotFound(html) Vistasfrom django.http import HttpResponse, Http404def example_get_project (request, project_id): try: p = Project.objects.get(project__pk=project_id) # pk synonym of id html = (" " " Project Name: %s " " Project Description: %s " " ") % (p.name, p.description) return HttpResponse(html) except Project.DoesNotExist: raise Http404 404 comn, buena idea tener una pgina de error estndar.Vistasdef 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="application/xhtml+xml") return r except Project.DoesNotExist: raise Http404def 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 travs de varias capasutilizando plantillasVistasEs la responsabilidad del programador devolver en cada vista un HttpResponse.VistasSe puede utilizar como un archivo...In [1]: from django.http import HttpResponseIn [2]: response = HttpResponse()In [3]: response.write("Here's the text of the Web page.")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.import csv, StringIOdef _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() returndef csv_log(request, project_id, username): ... response = HttpResponse(_gen(queryset), mimetype='text/csv') response['Content-Disposition'] = ('attachment; filename='
'tasklogs'
'-for-%s.csv') % username return responseAtributosHttpResponse.contentMtodosHttpResponse.__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()class HttpResponseRedirectclass HttpResponsePermanentRedirectclass HttpResponseNotModifiedclass HttpResponseBadRequestclass HttpResponseNotFoundclass HttpResponseForbiddenclass HttpResponseNotAllowedclass HttpResponseGoneclass HttpResponseServerErrorVistasEjercicio: crear una vista que devuelva un CSV con cuantas horas hizo cada usuario por tarea. Algo as: 'Usuario', 'Tarea', 'Horas'PlantillasDocumento 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 valoreslas etiquetas nos permiten controlar la logica de las plantillasfiltros permiten modificar el valor de las variablesIn [1]: from django.template import Template# Parsear cdigo de Templates y generar una instanciaIn [4]: t = Template("Hello, {{ name }}")In [6]: print tIn [8]: from django.template import Context# Una vez compilada podemos renderizar con un contextoIn [9]: c = Context({'name' : 'World'})In [10]: t.render(c)Out[10]: u'Hello, World'Plantillas{% extends "base_for_examples.html" %}{% block title %}Un proyecto: {{ project.name }}{% endblock title %}{% block content %} Un proyecto: Nombre: {{ project.name|upper }} Descripcin: {{ project.description|truncatewords:"10" }} {% endblock content %}Variable, el punto (.) se accede a los atributos de la variable, diccionario, llamada a una funcin sin arg.Etiqueta que define un bloque que se puede sobre escribir. Herencia.Filtro, mdifica el string, letras maysculas Indica de que template heredaPlantillasTEMPLATE_STRING_IF_INVALIDIn [1]: from django.template import Template, ContextIn [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 propiosPlantillasPlantillasadd {{ value|add:"2" }}cutdefaultescapefloatformat 34.23234,{{ value|floatformat }},34.2lengthsafeslugify {% if project_list %} {% for project in project_list %} {{project.name}}
{% for task in project.task_set.all %} {{ task.name }} {% endfor %} {% endfor %} {% else %} No projects in database Please add some projects in the database {% endif %}Plantillas{% cycle 'row1' 'row2' %}{% autoescape off %} {{ whatever }} {% autoescape %}{# comment #}{% ifequal user.id comment.user_id %} .. {% endifequal %}{% include "foo/bar.html" %}{% load %}{% url path.to.some_view arg1,arg2,name1=value1 %}{% with %}http://docs.djangoproject.com/en/dev/ref/templates/builtins/Plantillas{% block title %} Titulo{% endblock title %}{% block content %} Aqu el contenido de la pgina{% endblock content %}PlantillasHerencia / Extensin{% extends "base_for_examples.html" %}{% block title %}Un proyecto: {{ project.name }}{% endblock title %}{% block content %}{% block.super %} Un proyecto: Nombre: {{ project.name|upper }} Descripcin: {{ project.description|truncatewords:"10" }} {% endblock content %}PlantillasUn proyecto: Curso Django Pagina de la Aplicacin: TimeTracker Un proyecto: Nombre: CURSO DJANGO Descripcin: curso, curso, curse! Plantillashttp://localhost:8000/timetracker/example/project-with-shortcuts/1/PlantillasContextosIn [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]: cOut[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()-----------------------------------------------------PlantillasRequestContext (subclase de Context)Toma como un argumento RequestAgrega variables al contexto segn los Preprocesadores del Contexto indicados por TEMPLATE_CONTEXT_PROCESSORS.Se le pueden agregar preprocesadores al instanciarlosdef 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)Plantillas django.core.context_processors.authAgrega permisos {{perms}}, usuario {{ user }} django.core.context_processors.debugInformacin 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:funcin python, toma un argumento, devuelve un dictPlantillasTEMPLATE_CONTEXT_PROCESSORS = ( "django.core.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", "timetracker.views.add_next_url",)# --- request preprocessor / en viewsdef add_next_url (request): return { 'next_url' : request.GET.get('next', None) }Ejemplodef some_view(request): # ... return render_to_response('my_template.html', my_data_dictionary,
context_instance=RequestContext(request) )PlantillasPasando un instancia de contextoPlantillasEjercicio: 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 algn color.ManagersInterfaz que provee las operaciones de consulta a la base de datos In [1]: from timetracker.models import ProjectIn [2]: Project.objects.all()Out[2]: [, ]In [5]: Project.objects.filter(name='Curso Django')Out[5]: []Managersobjects puede ser renombrado en cada modelo from django.db import modelsclass TimeTrackerBaseModel (models.Model):...class Task (TimeTrackerBaseModel):... tasks = models.Manager()In [7]: from timetracker.models import TaskIn [8]: Task.objects.all()...: type object 'Task' has no attribute 'objects'In [9]: Task.tasks.all()Out[9]: [, ]ManagersSe pueden usar Manager modificados extendiendo la clase Manager instanciando en el modelo.Nota: Es el mtodo sugerido para agregar funcionalidad a nivel de las tablas.Agregar nuevos mtodos.Modificar el QuerySet inicial de los ManagersManagersAgregar nuevos mtodos.class TaskManager (models.Manager): def admin_task_count(self): from django.db import connection cursor = connection.cursor() cursor.execute(""" SELECT COUNT(*) FROM timetracker_task WHERE timetracker_task.owner_id = 1; """) return cursor.fetchall()[0][0] def query_admin_task_count(self): return self.filter(owner__username='admin').count()class Task (TimeTrackerBaseModel): ... tasks = TaskManager()ManagersAgregar nuevos mtodos.In [2]: from timetracker.models import TaskIn [3]: Task.tasks.all()Out[3]: [, ]In [4]: Task.tasks.admin_task_count()Out[4]: 2In [5]: Task.tasks.query_admin_task_count()Out[5]: 2Managersclass 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 # defaultclass Task (TimeTrackerBaseModel): ... tasks = TaskManager() uncompleted_tasks = UncompletedTaskManager() completed_tasks = CompletedTaskManager()Modificar el QuerySet inicial de los ManagersManagersIn [1]: from timetracker.models import TaskIn [2]: Task.uncompleted_tasks.all()Out[2]: []In [3]: Task.completed_tasks.all()Out[3]: []In [4]: Task.tasks.all()Out[4]: [, ]Modificar el QuerySet inicial de los ManagersEjercicio: crear/editar un Manager con una funcin que devuelve el promedio de horas para cada usuarioManagersManagers que estn 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.Un poco de AJAX y un poco de SerializacinAJAXUtilizamos un framework: jQueryAsynchronous Javascript and XMLurlpatterns += patterns('',
(r'^resources/(?P.*)$',
'django.views.static.serve',
dict(document_root=media_root,
show_indexes=True)),
)Necesitamos servir javascript.AJAXEjemplo: buscar html generado por una vista{% block script %} function get_project_tasks(url) { $.ajax({ type: "GET", url: url, dataType: "html", success: function(html){ $("#id_tasks_set").empty().append(html); } }); }{% endblock script %}
AJAXdef 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 })
{% for task in tasks %} Nombre: {{ task.name }} Descripcin: {{ task.description }} Fecha de Inicio: {{ task.start_date }} {% endfor %}SerializacinIn [11]: from django.core import serializersIn [12]: data=serializers.serialize("xml",Project.objects.filter(pk=1), fields=('name',))In [17]: dataOut[17]: '\nCurso DjangoIn [18]: for obj in serializers.deserialize("xml", data): ....: print obj, type(obj) ....: ....: Serializacinse pueden salvar objetos 'deserializados'se puede serializar a un archivose pueden instanciar...out = open("file.xml", "w")xml_serializer.serialize(SomeModel.objects.all(), stream=out)XMLSerializer = serializers.get_serializer("xml")xml_serializer = XMLSerializer()xml_serializer.serialize(queryset)data = xml_serializer.getvalue()for deserialized_object in serializers.deserialize("xml", data): if object_should_be_saved(deserialized_object): deserialized_object.save()AJAX y SerializacinEjercicio: crear una vista serialize los TaskLog y los muestre cada vez que se pidan utilizando AJAXjson_serializer = serializers.get_serializer("json")()json_serializer.serialize(queryset, ensure_ascii=False, stream=response)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.