Trabajando con las Vistas en DJango


En un artículo anterior de esta serie sobre DJango te hablé sobre los modelos de datos. En esta ocación veremos de forma general la creación de vistas en este Framework y a su vez cómo las mismas funcionan. Como siempre te digo, para las dudas puedes consultar siempre la documentación oficial o dejarme también un comentario al final del artículo.

¿Vistas….?

En Django, una vista no es más que una función que realiza una solicitud y retorna una respuesta, ambas web. Dicha respuesta puede ser de varias formas: un error 404, un página web y su contenido, una imagen, etc. El contenido de una vista no es más que toda la lógica que se necesita para devolver una respuesta, la cual se encuentra en el archivo views.py dentro de cada aplicación de Django.

	
	## En Python+Django
	## Primero importamos la clase HttpResponse del módulo djang.http, luego importamos el módulo de Python datetime
	
	from django.http import HttpResponse  
	import datetime
	
	## Luego definimos la función de vista hora_actual() que toma un parámetro de tipo HttpRequest llamado request 
	## Al final esta vista retorna un objeto HttpResponse que contiene la respuesta generada.
	## Cada función de vista es responsable de devolver un objeto HttpResponse.
	def hora_actual(request):
		now = datetime.datetime.now()
		html = "<html> <body>Ahora es %s.</body></html>" % now
		return HttpResponse(html)		

Manejando las urls.

	
	## La url debe quedar así:
	url(r'^now/$','frontend.views.hora_actual'),	

	## En el navegador debe visualizarse el resultado escribiendo:
	http://127.0.0.1/now/
	

Retornando errores.

Retornar errores en Django es muy fácil. Existen subclases de HttpResponse para un número común de códigos de estado HTTP otros a 200 que significa que todo ha ido bien.

	
	## Usando los HttpResponse y HttpResponseNotFound
	def my_view(request):
	# ...
		if foo:
			return HttpResponseNotFound('<h1> Page not found </h1>')
		else:
			return HttpResponse('<h1> Page was found </h1>')
			
	## urls.py
	url(r'^mivista/$','frontend.views.my_view'),
	
	## En el navegador:
	http://127.0.0.1/mivista/
	

Otra forma más elegante de dar tramiento a los errores es usando los módulos django.http
from django.http import Http404


	def detail(request, poll_id):
		try:
			p = Poll.objects.get(pk=poll_id)
		except Poll.DoesNotExist:
			raise Http404
		return render_to_response('polls/detail.html', {'poll': p})

Otro ejemplo con los modelos incluidos es el siguiente.

models.py

	
	## En models.py
	from django.db import models
	class Article(models.Model):
		pub_date = models.DateField()
		headline = models.CharField(max_length=200)
		content = models.TextField()
		reporter = models.ForeignKey(Reporter)
	

admin.py


	import models
	from django.contrib import admin
	
	admin.site.register(models.Article)

urls.py


	from django.conf.urls import patterns

	urlpatterns = patterns('',
		(r'^articles/(\d{4})/$', 'news.views.year_archive'),
		(r'^articles/(\d{4})/(\d{2})/$', 'news.views.month_archive'),
		(r'^articles/(\d{4})/(\d{2})/(\d+)/$', 'news.views.article_detail'),
	)
	

Escribiendo las vistas…

views.py

	
	def year_archive(request, year):
		## En la lista de artículos a_list se busca por el año de publicación.
		a_list = Article.objects.filter(pub_date__year=year)
		## La vista renderiza la plantilla news/year_archive.html y retorna la respuesta.
		return render_to_response('news/year_archive.html', {'year': year, 'article_list': a_list})
		
------------------------------------------------------------------------------------------------------------------

	## Código de la plantilla news/year_archive.html
	
	{% extends "base.html" %} ##Hereda de la plantilla "base.html"
	
	{% block title %}Articles for {{ year }}{% endblock %} ##Bloque de título de la página.
	
	{% block content %} ## Bloque de contenido de la página.
	
	<h1> Articles for {{ year }} </h1>
		## Para cada artículo en article_list imprimo ciertos campos.
		{% for article in article_list %}
			<p> {{ article.headline }} </p>
			<p>By {{ article.reporter.full_name }}</p>
			<p>Published {{ article.pub_date|date:"F j, Y" }}</p>
		{% endfor %}
		
	{% endblock %}	
	

Finalmente en el fichero base.html colocariamos el siguiente código

	
	{% load staticfiles %}
	<html>
		<head>
			<title> {% block title %}{% endblock %} </title>
		</head>
		<body>
			<img src="{% static "images/sitelogo.png" %}" alt="Logo" />
			{% block content %}{% endblock %}
		</body>
	</html>		
	

Te preguntarás a que se deben que existan las etiquetas como {% extends "base.html" %}, pues sucede que en Django existe la herencia de plantillas, que significa que Django primero carga base.html y luego el resto. Siempre puedes documentarte mejor respecto a este tema y al sistema de plantillas de Django en general.

¿Qué falta?. Bueno lo siguiente es probar que todo funcione, para ello en tu navegador web pones las urls http://127.0.0.1:8000/articles/year/ siendo year el número del año, http://127.0.0.1:8000/articles/year/month siendo month el número del mes y http://127.0.0.1:8000/articles/year/month/day/ siendo day el número del día del artículo publidado.

En próximos artículos seguiremos trabajando Django, continuando con algunos tips interesantes. Cualquier duda al respecto como ya te comenté puedes dejarla debajo. Hasta la próxima.