En el artículo anterior, analizamos por qué se necesitan las vistas basadas en clases (CBV) de Django y qué ventajas tienen en comparación con las vistas basadas en funciones (FBV). En esta publicación, profundizaremos en la Clase de Vista Básica de Django, que se puede considerar la base de todas las CBV.
“Para comprender correctamente las CBV, es importante entender primero cómo funciona django.views.View y qué estructura tiene.”
1. ¿Qué es la Clase de Vista de Django?
Todas las vistas basadas en clases de Django se utilizan heredando de la clase django.views.View
en el siguiente formato.
from django.views import View
class MyView(View):
def get(self, request, *args, **kwargs):
# Lógica a manejar cuando llega una solicitud GET
...
def post(self, request, *args, **kwargs):
# Lógica a manejar cuando llega una solicitud POST
...
Características de la Clase View
-
Separación de Métodos por Método HTTP
Cuando llega una solicitud, Django automáticamente llama a la función correspondiente al método de la solicitud, comoget()
,post()
,put()
,delete()
, a través del método internodispatch()
.- No es necesario usar condiciones como “if request.method == 'GET': … else: …” como en FBV, por lo que la estructura del código se mantiene limpia.
-
Herencia y Escalabilidad
Una puede crear múltiples vistas hijas heredando de la clase View, maximizando así la reutilización del código al colocar la lógica común en la clase padre y la lógica específica en la clase hija.
2. Estructura y Principio Básico de la Clase View
Ejemplo más simple
# views.py
from django.http import HttpResponse
from django.views import View
class HelloCBV(View):
def get(self, request, *args, **kwargs):
return HttpResponse("¡Hola, CBV!")
-
El método
get()
: se ejecuta cuando se envía una solicitud GET desde el navegador (por ejemplo, al ingresar una URL o hacer clic en un enlace). -
HttpResponse("¡Hola, CBV!")
: crea una respuesta en forma de texto y la devuelve directamente.
Conectando a urls.py
# urls.py
from django.urls import path
from .views import HelloCBV
urlpatterns = [
path('hello/', HelloCBV.as_view(), name='hello_cbv'),
]
-
El método
.as_view()
transforma la CBV en un formato comprensible por Django. -
Al conectarlo con un patrón URL, cuando llega una solicitud GET a
http://example.com/hello/
, se llama al métodoget()
deHelloCBV
.
3. Cómo usar la Clase View con Ejemplos Prácticos
Un caso en el que simplemente retornar “una cadena de texto” no es común. En la mayoría de los proyectos reales, a menudo se hace una respuesta JSON, renderización de plantillas, o consulta a la base de datos. Aquí exploraremos ejemplos de respuesta JSON y renderización de plantillas.
3.1 Ejemplo de Manejo de Respuesta JSON
# views.py
from django.http import JsonResponse
from django.views import View
class UserDataView(View):
def get(self, request, *args, **kwargs):
# Supongamos que se recibe el user_id como parámetro GET
user_id = request.GET.get('user_id', None)
if not user_id:
return JsonResponse({'error': 'No se proporcionó user_id'}, status=400)
# A nivel práctico, realizaría una consulta a la DB
user_data = {
'id': user_id,
'name': f'Usuario_{user_id}',
'role': 'admin'
}
return JsonResponse(user_data, status=200)
def post(self, request, *args, **kwargs):
# Se puede analizar JSON o datos de formulario desde el cuerpo de la solicitud POST.
# Se puede utilizar request.POST, request.body, request.FILES, etc.
# En los servicios reales, se escribiría la lógica para almacenar en la DB después de analizar el JSON
new_user_data = {
'id': 123,
'name': 'NuevoUsuario',
'role': 'member'
}
return JsonResponse(new_user_data, status=201)
-
JsonResponse
: es una herramienta conveniente para crear respuestas JSON en Django. -
request.GET
,request.POST
: se puede obtener los parámetros GET/POST de un objeto HttpRequest de Django. -
En la práctica, se integra con modelos DB o se usa Serializers para manejar datos de una manera más estructurada.
3.2 Ejemplo de Renderización de Plantillas
# views.py
from django.shortcuts import render
from django.views import View
class GreetingView(View):
def get(self, request, *args, **kwargs):
context = {
'title': 'Bienvenido a Mi Sitio',
'greeting': '¡Hola, esta es una GreetingView!'
}
return render(request, 'greeting.html', context)
<!-- templates/greeting.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ greeting }}</h1>
</body>
</html>
-
La función
render()
busca el archivo de plantilla (greeting.html
) y devuelve el HTML renderizado en forma deHttpResponse
. -
Así, dentro de la CBV, la renderización de plantillas se puede hacer de manera simple.
4. Ampliación y Reutilización de la Clase View
Una de las mayores razones por las que la Clase View es útil es la “reutilización del código”. A medida que el proyecto crece, es mucho más eficiente colocar en la clase padre la lógica que se necesita comúnmente entre varias vistas (p. ej., registro, verificación de permisos, procesamiento de datos comunes, etc.) y heredarla en las clases hijas.
4.1 Colocando la Lógica Común en la Clase Padre
# views.py
from django.http import JsonResponse
from django.views import View
class BaseLoggingView(View):
def dispatch(self, request, *args, **kwargs):
# Ejecuta la lógica común para todas las solicitudes (GET/POST, etc.)
print(f"[Log] Solicitud {request.method} en {request.path}")
return super().dispatch(request, *args, **kwargs)
class ChildLoggingView(BaseLoggingView):
def get(self, request, *args, **kwargs):
data = {'message': 'Respuesta GET del hijo'}
return JsonResponse(data)
def post(self, request, *args, **kwargs):
data = {'message': 'Respuesta POST del hijo'}
return JsonResponse(data)
-
El método
dispatch()
: es el método clave que permite controlar antes y después de que Django ejecute la lógica de vista. -
En este ejemplo, se registra cada solicitud antes de llamar realmente a
super().dispatch()
para ejecutarget()
,post()
, etc.
4.2 Añadiendo Funcionalidades a través de Mixin
En Django, a menudo se utiliza la técnica Mixin para “mezclar solo funciones específicas”. Por ejemplo, LoginRequiredMixin (verificación de inicio de sesión), PermissionRequiredMixin (verificación de permisos) se pueden mezclar con CBV.
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.http import JsonResponse
class SecuredView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
return JsonResponse({'message': 'Estás autenticado.'})
- Trabajar con Mixins se discutirá con más detalle más adelante cuando hablemos de vistas genéricas o gestión de permisos, así que por ahora es suficiente conocer que “así se pueden combinar funciones”.
5. Comparación Breve con FBV
Clasificación | FBV (Vista Basada en Funciones) | CBV (Vista Basada en Clases) |
---|---|---|
Forma de Escribir | Escrito en forma de función | Escrito en forma de clase & método |
Tratamiento de Métodos HTTP | if request.method == 'GET': ... else: ... |
get() , post() separando por métodos |
Posibilidad de Duplicación de Código | Es fácil que surjan códigos duplicados al complicarse la lógica | Posibilidad de reutilizar lógica común a través de herencia y Mixins |
Escalabilidad | Es común tener lógica común mezclada dentro de la función | Adecuado para responder a requisitos complejos con estructuras de herencia de clases |
Legibilidad | Ventajoso para prototipos sencillos | Más adecuado para mantener una estructura clara a medida que crece el tamaño |
-
FBV es bueno para escribir rápidamente funciones pequeñas o simples, mientras que CBV es favorable para la escalabilidad y el mantenimiento.
-
Particularmente en proyectos colaborativos o de mediana a gran escala, el uso de CBV es eficiente.
6. Profundizando: dispatch()
y Parámetros URL
6.1 Razón para Sobrescribir dispatch()
-
Pre y post procesamiento comunes: Aquí se puede manejar la lógica como comprobar la conexión a la base de datos, verificar permisos, o registrar cada vez que llega una solicitud.
-
Mapeo de Métodos: Internamente, usa
request.method.lower()
para hallar y llamarget()
,post()
,put()
, etc. Si se quiere personalizar un método adicional comoPATCH
, se puede optar por sobrescribirdispatch()
.
class CustomDispatchView(View):
def dispatch(self, request, *args, **kwargs):
print("Lógica de pre-procesamiento personalizada aquí.")
response = super().dispatch(request, *args, **kwargs)
print("Lógica de post-procesamiento personalizada aquí.")
return response
6.2 Recibiendo Parámetros URL
Si en urls.py
se especifica un parámetro de ruta como <int:user_id>/
, se puede recibir su valor a través de kwargs
en los métodos get()
o post()
de la CBV.
# urls.py
urlpatterns = [
path('user/<int:user_id>/', UserDetailView.as_view(), name='user_detail'),
]
# views.py
class UserDetailView(View):
def get(self, request, *args, **kwargs):
user_id = kwargs.get('user_id')
# Consulta a la base de datos usando user_id
return HttpResponse(f"ID de Usuario: {user_id}")
- Al igual que en FBV, se puede extraer y usar parámetros URL de
kwargs
.
7. Ejemplo de Casos Prácticos Más Ricos: Ejemplo de Un Foro Simple
Para aquellos que desean usar la Clase View de manera más práctica, aquí hay un código de ejemplo simple para crear una lista de publicaciones y una página de detalles. (La próxima publicación puede tratar sobre vistas genéricas, lo que facilitará implementar CRUD, pero aquí mostraré que esto también es posible con la Clase de Vista Básica).
# models.py - Modelo de ejemplo
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# views.py
from django.views import View
from django.shortcuts import render, get_object_or_404
from .models import Post
# Vista para ver la lista de publicaciones
class PostListView(View):
def get(self, request, *args, **kwargs):
posts = Post.objects.order_by('-created_at')
context = {'posts': posts}
return render(request, 'post_list.html', context)
# Vista para ver los detalles de una publicación
class PostDetailView(View):
def get(self, request, *args, **kwargs):
post_id = kwargs.get('pk')
post = get_object_or_404(Post, pk=post_id)
context = {'post': post}
return render(request, 'post_detail.html', context)
<!-- post_list.html -->
<!DOCTYPE html>
<html>
<head>
<title>Lista de Publicaciones</title>
</head>
<body>
<h1>Lista de Publicaciones</h1>
<ul>
{% for post in posts %}
<li>
<a href="{% url 'post_detail' post.id %}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
</body>
</html>
<!-- post_detail.html -->
<!DOCTYPE html>
<html>
<head>
<title>{{ post.title }}</title>
</head>
<body>
<h1>{{ post.title }}</h1>
<p>{{ post.content }}</p>
<p>Fecha de Creación: {{ post.created_at }}</p>
</body>
</html>
# urls.py
from django.urls import path
from .views import PostListView, PostDetailView
urlpatterns = [
path('posts/', PostListView.as_view(), name='post_list'),
path('posts/<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]
-
PostListView
: Al recibir una solicitud GET, consulta todas las publicaciones y las pasa a la plantilla (post_list.html
). -
PostDetailView
: Busca una publicación específica a través del parámetro URLpk
y la pasa a la plantilla (post_detail.html
). -
Así, se puede componer fácilmente páginas de lista y de detalles incluso usando solo la Clase de Vista Básica.
No obstante, para configurar todo el CRUD, se necesitarán lógicas de Crear/Actualizar/Eliminar. Lo que facilitará esto es el Vista Genérica que ofrece Django, y planeo tratar ese tema en el próximo artículo.
8. Conclusión y Previsión de la Próxima Publicación
Hasta aquí llega el ejemplo de cómo funciona la Clase de Vista Básica de Django y cómo se puede usar en la práctica. Resumiendo los puntos clave:
-
Hereda de django.views.View y sobreescribe métodos como
get()
/post()
/dispatch()
para responder a solicitudes HTTP. -
Escribiendo lógica común en la clase superior y redefiniendo solo las partes necesarias en las vistas hijas se maximiza la reutilización del código.
-
Se puede escribir lógica de vista simple para una variedad de escenarios como renderización de plantillas, respuesta JSON, consulta a la DB.
-
Como el ejemplo práctico (foro simple), se puede construir un proyecto solo con la Clase de Vista Básica.
Sin embargo, para manejar fácilmente operaciones de CRUD, es mucho más conveniente aprender sobre Vistas Genéricas que ofrece Django.
En la próxima publicación, me centraré en la clase FormView, que facilita el manejo de formularios. A través de esto, aprenderán a automatizar procesos como “recibir datos de usuarios, mostrarlos y, si hay errores, mostrar mensajes de error”.
¡La serie CBV continúa!
- Parte 3: “Facilitando el manejo de formularios con FormView”
- Parte 4: “Uso de ListView & DetailView”
- Parte 5: “Implementando CRUD con CreateView, UpdateView, DeleteView”
- … (y más)
Ver Publicaciones Anteriores
Materiales de Referencia Adicionales
-
Comunidad de Django – Puedes encontrar diversos ejemplos en la Comunidad de Django.
Espero que este artículo ayude a resolver algunas de las dudas sobre la estructura y el uso de la Clase de Vista Básica. En la próxima parte, aprenderemos cómo manejar el proceso de “completar formularios→validación→manejo de errores→redireccionar al éxito” de manera sencilla con FormView.
“La Clase de Vista de Django no solo separa el código por métodos HTTP, sino que se convierte en una herramienta poderosa para mejorar drásticamente la escalabilidad y el mantenimiento en proyectos grandes.”
¡Sigamos explorando CBV para un desarrollo más productivo en Django!
No hay comentarios.