Frameworks

Tutorial de Django: Vistas y Urls: Procesar los datos.

En los post anteriores vimos como se iniciaba una aplicación, creamos la base de datos y los modelos; y vimos como podíamos introducir las imágenes de nuestro álbum de fotos de dos formas, usando el shell y a través del administrador que nos ofrece Django por defecto. Hoy usaremos las vistas para mostrar nuestra galería.

Publicado el 18 de Noviembre de 2014
Compartir

Ver Indice Tutorial

En los post anteriores vimos como se iniciaba una aplicación, creamos la base de datos y los modelos; y vimos como podíamos introducir las imagenes de nuestro álbum de fotos de dos formas, usando el shell y a través del administrador que nos ofrece Django por defecto. Hoy usaremos las vistas para mostrar nuestra galería.

Para ver como gestiona Django las vistas , las relaciona con el modelo de datos y envía esa información al navegador vamos a empezar creando una vista sencilla, simplemente vamos a mostrar un mensaje por pantalla.

Editamos el fichero ./album/views.py

from django.http import HttpResponse


def first_view(request):
    return HttpResponse('Esta es mi primera vista!')

Una vista es una función o un método que básicamente hace dos cosas, toma como argumento un objeto HttpRequest , en el que va la información referente a la solicitud que estamos haciendo, como por ejemplo si el método empleado es POST o GET o el directorio donde está la página solicitada; y devuelve un objeto HttpResponse con la información de la página que va a mostrar o una excepción si algo ha ido mal.

Ahora tenemos que asociar la vista que acabamos de definir con una dirección , para hacerlo vamos a manejar dos ficheros, uno lo crea Django al iniciar el proyecto y está en ./myapps/urls.py , el otro lo tendremos que crear nosotros dentro del directorio de nuestra aplicación, ./album/urls.py .

Vamos a editar el primero ./myapps/urls.py .

from django.conf.urls import patterns, include, url
from django.contrib import admin


urlpatterns = patterns('',
    url(r'^admin/', include(admin.site.urls)),
)

Si nos olvidamos de las líneas que tiene comentadas vemos que tiene una relación entre la dirección /admin y el módulo admin.site.urls . Esta es la forma que tiene Django de enlazar la dirección con el fichero urls.py propio de la aplicación admin que ya hemos usado en los capítulos anteriores. De esta forma al dirigirnos a http://127.0.0.1:8000/admin/ lo que hacemos es empezar a usar dicho fichero para los siguientes enlaces que usemos, como por ejemplo http://127.0.0.1:8000/admin/album/photo/.

Vamos a hacer lo mismo con nuestra aplicación album. Añadimos la siguiente línea como nuevo argumento de la función patterns() para dejarla de la siguiente forma.

from django.conf.urls import patterns, include, url
from django.contrib import admin


urlpatterns = patterns('',
    url(r'^album/', include('album.urls')),
    url(r'^admin/', include(admin.site.urls)),
)

Ahora ya sabemos que al incluir en el navegador una dirección que comience por /álbum enviaremos el resto de la cadena como argumento a la función patterns que tenemos en el fichero ./album/urls.py .

Creamos y editamos este fichero para dejarlo así.

from django.conf.urls import patterns, url
from album import views


urlpatterns = patterns('',
                       url(r'^$', views.first_view, name='first-view'),
                       )

de esta forma, la dirección /álbum estará apuntando a la vista first_view() .

La función url() necesita dos argumentos , el primero será una expresión regular (regex) que utiliza para identificar la dirección que escribimos en el navegador, el segundo es la función a la que llamará, first_view() para nosotros, pasándole como primer argumento el objeto HttpRequest que mencionábamos antes. Además se pueden pasar tres argumentos opcionales, name lo usaremos para identificar nuestra url de forma única y nos servirá para poder cambiar la url sin tener que modificar las partes del proyecto donde hacemos referencia a ella. Los otros dos argumentos son kwargs y prefix que no usaremos en nuestra aplicación.

Si arrancamos el servidor de pruebas y buscamos en el navegador la dirección http://127.0.0.1:8000/album/ veremos lo siguiente:

Imagen 0 en Tutorial de Django: Vistas y Urls: Procesar los datos.

Con esto hemos visto como unir la dirección del navegador con nuestras vistas, veamos ahora como relacionar la vista con el modelo de datos y devolver esta información al navegador. Para hacerlo vamos a crear un nuevo directorio dentro de nuestra aplicación ./myapps/album/templates/album/ de modo que tengamos esto:

(tutorial)openwebinars@~/aplicaciones/myapps: tree album
album
├── admin.py
├── __init__.py
├── migrations
│   ├── 0001_initial.py
│   ├── 0001_initial.pyc
│   └── __init__.py
├── models.py
├── templates
│   └── album
├── tests.py
├── urls.py
└── views.py

En él incluiremos los ficheros html propios de nuestra aplicación. Creamos el fichero category.html de la siguiente forma:


 
{{ object_list }}

Ahora veremos que es object_list.

Editamos de nuevo el fichero ./album/views.py

from django.http import HttpResponse
from django.shortcuts import render
from album.models import Category, Photo


def first_view(request):
    return HttpResponse('Esta es mi primera vista')


def category(request):
    category_list = Category.objects.all()
    context = {'object_list': category_list}
    return render(request, 'album/category.html', context)

category_list contiene todas las categorías disponibles y las pasamos como argumento a la función render() . Esta función es un atajo que nos proporciona Django para devolver el objeto HttpResponse a partir de una plantilla (category.html) y la información necesaria para componerla (context).

Lo unimos con ./album/urls.py

from django.conf.urls import patterns, url
from album import views


urlpatterns = patterns('',
                       url(r'^$', views.first_view, name='first-view'),
                       url(r'^category/$', views.category, name='category-list'),
                       )

y buscamos la nueva dirección en el navegador, http://127.0.0.1:8000/album/category/

Imagen 1 en Tutorial de Django: Vistas y Urls: Procesar los datos.

Como vemos, con object_list hemos incluido la lista de objetos Category dentro de nuestra plantilla category.html , por tanto ya tenemos toda la información relativa a las categorías.

Vamos a incluir una nueva vista que nos muestre el detalle de una de las categorías; editamos de nuevo el fichero ./album/views.py

def category_detail(request, category_id):
    
    category = Category.objects.get(id=category_id)
    context = {'object': category}
    return render(request, 'album/category_detail.html', context)

Ahora la función category_detail() recibe dos argumentos, request y el identificador de la categoría que queremos mostrar.

En el directorio de ./album/templates/album creamos una nueva plantilla category_detail.html


 
{{ object.id }}, {{ object.name }}, {{ object.photo_set.all }}

De forma similar a la vista anterior, en la variable context que pasamos a la función render() tenemos un objeto Category del que podemos extraer su id, name y las fotos que pertenecen a dicha categoría entre otras cosas.

Por último conectamos la vista con una url , esta vez tenemos que indicar de que categoría queremos extraer el detalle, para conseguirlo usaremos (?P<category_id>\d+) siendo category_id el segundo parámetro que hemos pasado a la función category_detail() .

from django.conf.urls import patterns, url
from album import views


urlpatterns = patterns('',
                       url(r'^$', views.first_view, name='first-view'),
                       url(r'^category/$', views.category, name='category-list'),
                       url(r'^category/(?P<category_id>\d+)/detail/$', views.category_detail,
                           name='category-detail'),
                       )

Si abrimos el enlace http://127.0.0.1:8000/album/category/2/detail/ en el navegador veremos el resultado.

Imagen 2 en Tutorial de Django: Vistas y Urls: Procesar los datos.

Ya vimos en posts anteriores que Django nos ofrece soluciones para facilitarnos el trabajo y en esta ocasión podemos aprovecharnos de las vistas genéricas , como ListView y DetailView para obtener una lista de todos los objetos pertenecientes a un modelo y el detalle de uno de ellos. Vamos a hacerlo para la clase Photo.

Abrimos ./album/views.py e incluimos este código.

from django.views.generic import ListView, DetailView


class PhotoListView(ListView):
    model = Photo


class PhotoDetailView(DetailView):
    model = Photo

Como podemos ver solamente tenemos que decirle sobre que modelo queremos trabajar.

Creamos dos nuevos templates, photo_list.html para el listado de fotos y photo_detail.html para el detalle. Las vistas genéricas usan por defecto el siguiente sistema a la hora de buscar la plantilla html, < app _name>/< model _name>_list.html y < app _name>/< model _name>_detail.html , para ListView y DetailView respectivamente. Si queremos especificar un nombre de plantilla distinto podemos usar el atributo template_name .

Creamos ./album/templates/album/photo_list.html


 
{{ object_list }}

y ./album/templates/album/photo_detail.html


 
{{ object.id }}, {{ object.title }}

Por último, unimos la vista con urls editando ./album/urls.py para dejarlo así.

  
from django.conf.urls import patterns, url
from album import views


urlpatterns = patterns('',
                       url(r'^$', views.first_view, name='first-view'),
                       url(r'^category/$', views.category, name='category-list'),
                       url(r'^category/(?P<category_id>\d+)/detail/$', views.category_detail,
                           name='category-detail'),
                       url(r'^photo/$', views.PhotoListView.as_view(), name='photo-list'),
                       url(r'^photo/(?P<pk>\d+)/detail/$', views.PhotoDetailView.as_view(),
                           name='photo-detail'),
                       )
  

Aquí tenemos que tener en cuenta dos cosas, al usar el sistema de vistas genéricas estamos trabajando con clases no con funciones por lo que tenemos que llamar al método as_view() , también hemos dejado de usar (?P<photo_id>\d+) y lo hemos sustituido por (?P<pk>\d+) .

Ya podemos ver en el navegador que el resultado es el mismo aunque esta vez nuestras vistas son mucho más sencillas.

http://127.0.0.1:8000/album/photo/

Imagen 3 en Tutorial de Django: Vistas y Urls: Procesar los datos.

http://127.0.0.1:8000/album/photo/1/detail/

Imagen 4 en Tutorial de Django: Vistas y Urls: Procesar los datos.

Esto es solo una parte ya que el sistema de vistas genéricas es mucho más potente y lo veremos con más detalle en el siguiente post.

Como ejercicio podemos cambiar las funciones category() y category_detail() para usar generic views , teniendo en cuenta que estamos trabajando con la plantilla category.html y no es lo que usará por defecto la vista ListView.


Compartir este post

También te puede interesar...

Tecnología

Tutorial de Django: Cómo usar Git y Bootstrap con Django.

22 Enero 2015 José Plana
Artículos
Ver todos