Vistas basadas en clases

Una vista es un callable que recibe una solicitud y devuelve una respuesta. Esto puede ser más que solo una función, y Django proporciona ejemplos de algunas clases que se pueden utilizar como vistas. Estas permiten estructurar tus vistas y reutilizar código aprovechando la herencia y las mezclas. También hay algunas vistas genéricas para tareas que trataremos más adelante, pero puede que desees diseñar tu propia estructura de vistas reutilizables que se adapte a tu caso de uso. Para detalles completos, consulta la documentación de referencia sobre vistas basadas en clases.

Ejemplos básicos

Django proporciona clases de vistas base que se ajustarán a una amplia gama de aplicaciones. Todas las vistas heredan de la clase View, que gestiona la vinculación de la vista en las URL, el despliegue de métodos HTTP y otras características comunes. RedirectView proporciona un redireccionamiento HTTP, y TemplateView extiende la clase base para hacer que también renderice una plantilla.

Uso en tu archivo URLconf

La forma más directa de utilizar vistas genéricas es crearlas directamente en tu archivo URLconf. Si solo estás cambiando unos pocos atributos en una vista basada en clase, puedes pasarlos a la llamada del método as_view() mismo:

from django.urls import path
from django.views.generic import TemplateView

urlpatterns = [
    path("about/", TemplateView.as_view(template_name="about.html")),
]

Cualquier argumento pasado a as_view() sobreescribirá las atributos establecidos en la clase. En este ejemplo, se establece template_name en el TemplateView. Un patrón de sobrescritura similar puede usarse para el atributo url de RedirectView.

Clases heredadas de vistas genericas

La segunda forma más poderosa de utilizar vistas genéricas es heredar de una vista existente y sobreescribir atributos (como template_name) o métodos (como get_context_data) en tu subclase para proporcionar nuevos valores o métodos. Considera, por ejemplo, una vista que solo muestra un template, about.html. Django tiene una vista genérica para hacer esto - TemplateView - así que podemos heredar de ella y sobreescribir el nombre del template:

# some_app/views.py
from django.views.generic import TemplateView


class AboutView(TemplateView):
    template_name = "about.html"

Luego debemos agregar esta nueva vista en nuestro archivo de configuración de URLs. TemplateView es una clase y no una función, por lo que apuntamos la URL al método de clase as_view(), el cual proporciona un acceso funcional a las vistas basadas en clases:

# urls.py
from django.urls import path
from some_app.views import AboutView

urlpatterns = [
    path("about/", AboutView.as_view()),
]

Para más información sobre cómo utilizar las vistas genéricas integradas, consulte el próximo tema en vistas de clase basadas en generic class-based views.

Soporte para otros métodos HTTP

Supongamos que alguien quiere acceder a nuestra biblioteca de libros sobre HTTP utilizando las vistas como una API. El cliente de la API se conectaría de vez en cuando y descargaría los datos de libro para los libros publicados desde la última visita. Pero si no hubiera nuevos libros desde entonces, sería un desperdicio del tiempo de CPU y banda ancha obtener los libros desde la base de datos, renderizar una respuesta completa y enviarla al cliente. Podría ser preferible preguntar a la API cuándo se publicó el libro más reciente.

Mapeamos la URL a la vista de lista de libros en el URLconf:

from django.urls import path
from books.views import BookListView

urlpatterns = [
    path("books/", BookListView.as_view()),
]

Y la vista:

from django.http import HttpResponse
from django.views.generic import ListView
from books.models import Book


class BookListView(ListView):
    model = Book

    def head(self, *args, **kwargs):
        last_book = self.get_queryset().latest("publication_date")
        response = HttpResponse(
            # RFC 1123 date format.
            headers={
                "Last-Modified": last_book.publication_date.strftime(
                    "%a, %d %b %Y %H:%M:%S GMT"
                )
            },
        )
        return response

Si la vista se accede desde una solicitud GET, se devuelve una lista de objetos en la respuesta (utilizando el template book_list.html). Pero si el cliente emite una solicitud HEAD, la respuesta tiene un cuerpo vacío y el encabezado Last-Modified indica cuándo se publicó el libro más reciente. Basándose en esta información, el cliente puede o no descargar la lista de objetos completa.

Vistas basadas en clase asíncronas

Además de los métodos de manejo ya mostrados (def), las clases View pueden definir métodos de manejo asíncronos (async def) para aprovechar el código asíncrono utilizando await:

import asyncio
from django.http import HttpResponse
from django.views import View


class AsyncView(View):
    async def get(self, request, *args, **kwargs):
        # Perform io-blocking view logic using await, sleep for example.
        await asyncio.sleep(1)
        return HttpResponse("Hello async world!")

Dentro de una sola clase de vista, todos los métodos de manejo definidos por el usuario deben ser síncronos, utilizando def, o todos asíncronos, utilizando async def. Se levantará una excepción ImproperlyConfigured en as_view() si se declaran tanto def como async def.

Django detectará automáticamente las vistas asíncronas y las ejecutará en un contexto asíncrono. Puede leer más sobre el soporte de Django para tareas asíncronas, y cómo utilizar mejor las vistas asíncronas, en Soporte asíncrono.