Thumbnail: django

La Biblioteca, aplicación en Django 1.8 | Parte VI

por , en la categoría de Django
10 minuto(s) de lectura
Este artículo hace parte de la serie «Django dummies»:
  1. La Biblioteca, aplicación en Django 1.8 | Parte I
  2. La Biblioteca, aplicación en Django 1.8 | Parte II
  3. La Biblioteca, aplicación en Django 1.8 | Parte III
  4. La Biblioteca, aplicación en Django 1.8 | Parte IV
  5. La Biblioteca, aplicación en Django 1.8 | Parte V
  6. La Biblioteca, aplicación en Django 1.8 | Parte VI
  7. La Biblioteca, aplicación en Django 1.8 | Parte VII

Introducción

Hoy vamos a continuar con la sexta parte de la creación de la Biblioteca, una aplicación Django nivel intermedio, en la entrega anterior realizamos dos vistas, una para obtener todos los libros presentes en la base de datos y otra para el detalle de cada libro, con sus correspondientes templates y mapeos de url. Hoy vamos a hablar acerca de dos características muy interesantes de este framework: Las vistas genéricas y la herencia de templates.

Vistas genéricas

Cuando Django fue creado, el equipo de desarrollo del framework no quería acogerse estrictamente a una arquitectura determinada (aunque ya todos sabemos que la arquitectura del mismo es una variante del patrón MVC), ellos querían crear un framework que ahorrara muchas de las tareas comunes que tiene cualquier aplicación web como por ejemplo: crear, actualizar, eliminar y borrar registros de una tabla de una base de datos sin importar sus relaciones. El objetivo era que el desarrollador se centrara en implementar el comportamiento especifico de la aplicación y no perder mucho tiempo en cosas secundarias. Es así como nacieron las vistas genéricas.

Herencia de templates

El motor de templates de Django nos proporciona una característica bastante útil, podemos definir templates generales que tendrán elementos html comunes de todas las demás, permitiendo así no repetir código html y ahorrándonos algunos dolores de cabeza. Tal vez quieras realizar una template general donde coloques el código de tu barra de menú y quizá un footer. De esta forma solo tendrías que definir el contenido de templates especificas, sin repetir código del menú o footer en ellas.

Usando vistas genéricas en nuestra app

Es hora de usar lo que hemos aprendido en nuestra aplicación, primero vamos con las vistas genéricas.

Abre el archivo views.py presente dentro de la carpeta sitiolectura/biblioteca coloca lo siguiente

#...another imports 
#importamos las vistas genericas de Django para crear, actualizar y eliminar
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from biblioteca.forms import FormCrearLibro #luego veremos para que 
from django.core.urlresolvers import reverse_lazy

#...another views
#...

#--------------------------Vistas genericas----------------------
class LibroCreateView(CreateView):
	"""Con esta vista generica, tenemos la logica
	para crear un nuevo Libro"""	
	model = Libro
	#Caracteristicas especiales para el form de crear
	form_class = FormCrearLibro
	template_name = 'biblioteca/uc_libro.html'

class LibroUpdateView(UpdateView):
	"""Esta vista nos permite actualizar un Libro existente"""
	model = Libro
	form_class = FormCrearLibro
	template_name = 'biblioteca/uc_libro.html'	


class LibroDeleteView(DeleteView):
	"""Esta vista nos permitira eliminar un Libro existente"""
	model = Libro
	success_url = reverse_lazy('sitio:index')

Cosas por decir acá:

  1. Hemos definido tres vistas genéricas, para crear, actualizar y eliminar Libros.

  2. LibroCreateView hereda de la clase CreateView quien nos proporciona atributos y comportamientos para realizar la acción de crear, la variable model de todas las vistas, hace referencia al modelo en el cual se realizará la acción según corresponda (crear, eliminar, actualizar). No nos tenemos que preocupar sobre consultas SQL y demás detalles para que se vea reflejado las acciones en la BBDD.

  3. Como dijimos en el post anterior, una vista debe de retornar un objeto HttpResponse, que a groso modo es la template asociada a la vista. Gracias a la variable template_name podemos especificar que template retorna la vista genérica.

  4. Para la vista de crear y actualizar usamos la misma template, Django se encarga de proporcionarnos el comportamiento adecuado dependiendo de cada caso.

  5. Para la ultima vista genérica (LibroDeleteView), la variable success_url nos permite establecer la ruta donde seremos enviados justo después de eliminar un libro. Podemos acceder a los datos de un Libro desde la template por medio de una variable, que será el nombre del modelo en minúscula, en nuestro caso será libro.

La variable form_class presente en las vistas de creación y actualización hacen referencia a cómo será construido los formularios de actualizar y crear; ya se sabe que para crear un Libro necesitamos un campo de nombre, otro campo de autor, de editor, entre otros (los campos que definimos en el modelo de Libro). Necesitamos proporcionarle a la vista genérica la información necesaria para que esta nos construya el formulario adecuado, para ello debemos de hacer uso de la API de formularios de Django.

dentro de la carpeta sitiolectura/biblioteca crea un nuevo archivo, lo llamaremos forms.py, en el coloca lo siguiente:

#importamos la api forms desde django
from django import forms 
from django.forms import ModelForm

#Importamos los modelos, por ahora solo Libro
from biblioteca.models import Libro

class FormCrearLibro(forms.ModelForm):
	"""Clase para crear un formulario 
	a partir de un modelo definido"""
    class Meta:
    	"""Clase interna, aca definimos la informacion necesaria:
    	1. de que modelo es el form a costruir (variable model)
    	2. cuales campos tendra el formulario (variable fields)"""
        model = Libro
    	fields = ['titulo', 'autores', 'editor', 'fecha_publicacion', 'portada', 'sinopsis']

Lo próximo que vamos a hacer es crear en la carpeta biblioteca/templates/biblioteca una nueva template llamada uc_libro.html que será usada por dos de las vistas genéricas hechas anteriormente, dentro de ella coloca lo siguiente:



<form action="" enctype="multipart/form-data" method="POST">
	{% csrf_token %}
	<table>
		{{ form.as_table }}	
	</table>
	<button type="submit" name="crear" value="crear">Enviar</button>
</form>

Cosas que decir hasta acá:

  1. La template anterior será usada por la vista LibroCreateView y LibroUpdateView para gestionar las acciones de creación y actualización de libros.

  2. el formulario creado en nuestro archivo forms.py viene en forma de código html en la variable form, esa variable es la que vemos en la anterior template. Existen varias formas de mostrar ese formulario, hemos elegido mostrarlo como una tabla, por eso hicimos form.as_table.

  3. la etiqueta csrf_token debe de ir siempre que vayamos actualizar o crear registros en la base de datos, esto nos protege contra ataques de CSRF

Bien, tenemos la template para las dos primeras vistas genéricas pero aun nos falta algo, una segunda template para la vista de LibroDeleteView. Cuando usamos está vista genérica, debemos de proporcionar una template de confirmación, Django así nos lo manda. El nombre que debe recibir dicha vista es modelo_confirm_delete, donde modelo hace referencia al nombre del modelo del ítem que se va a eliminar. Como en nuestro caso vamos a eliminar libros, pues entonces esa template deberá tener el nombre de libro_confirm_delete.html. En esa template coloca lo siguiente:



<form action="" method="POST">{% csrf_token %}
	<p>¿Deseas borrar el libro {{ libro.titulo }}?</p>
	<div>
		<button type="submit">Confirmar</button>
		<a href="{% url 'sitio:index' %}">Cancelar</a>
	</div>
</form>	

El anterior template es de confirmación, si el usuario da click en el botón confirmar, entonces será dirigido a una template cuyo name será index y el libro será borrado, mientras que si da click en cancelar será llevado al index sin que el libro sea borrado, para ello usamos un tag de url; ‘sito:index’ hace referencia a toda la url del index, es como concatenar la url cuyo namespace es “sitio” con la url cuyo name es “index”. Gracias al contexto dado por la vista genérica, accedemos a los datos de un Libro, usando la variable libro, puedes pensar en esa variable como un objeto Libro.

Por último debemos de asociar las vistas con las urls, para que todo funcione perfectamente, abre el archivo sitiolectura/biblioteca/urls.py y coloca lo siguiente

from django.conf.urls import include, url
#Le decimos a Django que de este directorio importe el fichero views
from . import views 

urlpatterns = [
	#index, muestra todos los libros
    url( r'^$' , views.books, name='index' ),
    #Detalle de un libro en particular
    url(r'^books/(\d+)/$', views.detail_book, name='detail-book'),
    #Crear libros
	url(r'^crear-libro$', views.LibroCreateView.as_view(), name='crear'),
	#Update Libros
	url(r'^(?P<pk>\d+)/update-libro$', views.LibroUpdateView.as_view(), name='update'),
	#Delete Libros
	url(r'^(?P<pk>\d+)/delete-libro$', views.LibroDeleteView.as_view(), name='delete'),
]

Cosas por decir acá:

  1. Como sabemos las vistas son métodos o funciones, aunque si has prestado atención has podido ver que las vistas genéricas son clases python; a esto Django le denomina vistas basadas en clases. Pero debe de existir la forma de “pasar” esas clases a un equivalente en funciones, para eso hacemos uso del método as_view().

  2. El index de nuestra aplicación mostrará ahora el listado de libros de la base de datos.

¿Qué tal si probamos todo?

  1. Si colocas en el navegador localhost:8000/biblioteca/ deberas ver el listado de todos los libros de la base de datos

index

  1. Para crear un nuevo libro vamos a localhost:8000/biblioteca/crear-libro deberías ver el formulario de creación de libros, Django sabe que un atributo manyToMany como Autores, será una lista de opciones múltiples (puedes elegir mas de un autor para un mismo libro), y que un atributo que sea primaryKey será traducido a una lista desplegable, como es el caso de Editor.

crear

  1. Ahora vamos a editar un libro existente, digamos el libro 2, vamos a localhost:8000/biblioteca/2/update-libro deberás ver el formulario con los datos actuales del libro 2, listos para ser editados

update

  1. Lo ultimo es probar el borrado de libros, digamos el libro 2, vamos a localhost:8000/biblioteca/2/delete-libro, debe dirigirte a una template de confirmación.

confirmacion

  1. Dale clic en aceptar y deberás ser redirigido al index, donde podrás comprobar que el libro ha sido borrado. En mi caso el libro 2 es Cien años de Soledad, y en la imagen puedes ver que ya ha sido borrado.

borrado

Bueno y eso ha sido todo, hemos hecho un simple CRUD con ayuda de las vistas genéricas de Django, te invito a que leas la documentación de la API de formularios, pues no hablamos mucho acerca de este tema en el posts. Lo único que falta para que acabemos nuestra biblioteca es hacer uso de la herencia de templates, ese será tema para otro posts, si tienes dudas puedes dejarlas en los comentarios. No siendo mas nos vemos en otra ocasión.

print("Hasta pronto")

Siguiente artículo en la serie: La Biblioteca, aplicación en Django 1.8 | Parte VII

aplicacion, Django 1.8, Biblioteca
comments powered by Disqus