Empezamos con este artículo a ver cómo podemos utilizar las Django class based views con los modelos de datos. ¿Verdad que esto se pone cada vez más interesante? Hast el momento hemos visto un uso muy genérico de esta tecnología, pero con lo que ya sabemos deberíamos ser capaces de mostrar páginas web y gestionar el trabajo con formularios.

Es bastante común en las aplicaciones modernas que los datos vengan de algún sitio, es decir, que no estén codificados a fuego en el HTML. Lo más normal es que los datos provengan de una base de datos sql. En su afán de ahorrarnos trabajo los desarrolladores de Django han creado todo un conjunto de mixin y vistas específicas que nos simplifican el trabajo.

Mostrar un objeto.

Supongamos que volemos mostrar la información que tenemos de un usuario. Como sabréis el modelo User de Django guarda los datos de los usuarios y podemos encontrarlo en django.contrib.auth.models. Lo que queremos es que especificando una clave primaria en la url podamos mostrar en nuestra plantailla la información del usuario correspondiente a dicha clave.

Es decir, se trata de mostrar la información que se corresponda con urls de este tipo:

'^prefix/(?P<pk>\d+)/$'

o bien, si trabajamos con slugs

'^prefix/(?P<slug>[-w]+)/$'

Django nos proporciona la clase DetailView para hacer precisamente esto. Es decir, para ahorrarnos la mayor parte del trabajo de buscar el objeto que se corresponda con la clave primaria o slug (lo estoy utilizando como sinónimo de clave única) y pasarlo a la plantilla para su presentación. Por si alguno se lo pregunta DetailView se encuentra en django.views.generic.detail. Veamos cómo es la clase DetailView por dentro:

Esta clase hereda de SingelObjectTemplateResponseMIxin y de BaseDetailView. La primera a suvez es hija de una conocida nuestra TemplateResponseMixin de la que sobrescribe el método get_template_names a fin de establecer un nombre de plantilla pro defecto, que en els caso de los modelos es del tipo app/modelo_detail.html, es decir, en nuestro ejemplo, si no indicamos plantilla, Django la buscará por defecto en auth/user_detail.html.

Por su lado BaseDetailView es hija de SingleObjectMixin y de View e implementa el método get y le pasa al contexto de la plantilla la variable object con el contenido del objeto que se corresponde a la clave única que hemos pasado en la url. Como que trabajar con una variable llamada object puede resultar un tanto confuso, Django también pasa el mismo contenido en una variable que tienen el mismo nombre del objeto si al definir el model hemos establecido el verbose_name, o bien utilizará el que le indiquemos en el atributo context_object_name al definir la clase.

SingleObjectMixin es la clase encargada de hacer el trabajo duro, y como no, también implementa el método get_context_data para poder pasar más información a la plantilla. Así pues, mostrar un objeto puede ser tan sencillo como esto:

A urls.py añadimos:

url(r'^user/(?P<pk>\d+)/$', UserView.as_view(),
        name='main_user'),

No olvidemos importar UserView que crearemos dentro de views.py y que puede ser tan simple como:

class UserView(DetailView):
    model = User

User tiene asignado un verbose_name='User'. Django por tanto pasa a la plantilla tanto la variable object como la variable user, y por tant, en condiciones normales podríamos utilizar tanto un nombre de varaible como otro.

En nuestro caso, y si como yo tenéis en context_processors la línea 'django.contrib.auth.context_processors.auth' os encontrarés que la variable user "no fuciona". Esto es así porqué el context processor crea también una variable llamada user con los datos del usuario autentificado (si existe) y como se le asigna justo antes de generara la plantilla, el contenido de esta variable prevalicerá sobre el contenido que le pasamos desde la vista. Así pues, primer aviso, si la variable no contienen lo que esperáis vigilad el context_processors.

Una cosa que me sorprendió del SingleObjectMixin es que además del método get_object implementa también get_queryset. De hecho, get_object llama a get_queryset y le aplica un filtro por clave primaria (pk) o por slug. ¿Qué quiere decir eso? Pues sencillamente, que tenemos un nivel extra de flexibilidad a la hora de determinar si un objeto es presentable o no. Basta con sobreescribir o extender el método get_queryset e independientemente de la existencia de la clave única en la base de datos, podemos hacer que el objeto no se muestre. Por ejemplo, supongamos que en el ejemplo anterior no queremos mostrar los datos del usuario admin. Podríamos escribir:

class UserView(DetailView):
    model = User

    def get_queryset(self):
        query = super(UserView, self).get_queryset()
        return query.exclude(username='admin')

de manera que UserView nos mostrará la información de cualquier usuario excepto la del usuario admin, en este caso mostraría el error 404.

SingleObjectMixin, como hemos dicho, puede retornarnos un objeto a partir de su clave primaria o bien a partir del slgu. Normalmente utilizamos uno u toro, el orden de prioridad es que primero intenta por clave primaria (pk) y en caso de que este parámetro no exista mirará si tenemos definido el parámetro slug.

En el próximo apunte hablaremos del CRUD.

blog comments powered by Disqus