Mixins y decoradores en vistas Django

Intermedio
Django
Django
Actualizado: 18/04/2026

Mixins de autenticación y autorización

Django proporciona mixins listos para usar que añaden control de acceso a cualquier CBV mediante herencia múltiple. La clave es colocarlos antes de la clase de vista en la lista de herencia.

Diagrama conceptual de Mixins y decoradores en vistas Django

LoginRequiredMixin

Redirige al usuario a la página de login si no está autenticado:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView, CreateView
from django.urls import reverse_lazy
from .models import Pedido

class MisPedidosView(LoginRequiredMixin, ListView):
    model = Pedido
    template_name = 'pedidos/mis_pedidos.html'
    login_url = '/usuarios/login/'         # URL de login personalizada
    redirect_field_name = 'siguiente'      # Nombre del parámetro de redirección

    def get_queryset(self):
        return super().get_queryset().filter(usuario=self.request.user)

El valor por defecto de login_url es el definido en settings.LOGIN_URL (/accounts/login/).

PermissionRequiredMixin

Exige que el usuario tenga uno o varios permisos específicos:

from django.contrib.auth.mixins import PermissionRequiredMixin
from django.views.generic.edit import CreateView
from .models import Producto

class ProductoCreateView(PermissionRequiredMixin, CreateView):
    model = Producto
    fields = ['nombre', 'precio', 'categoria']
    permission_required = 'catalogo.add_producto'    # Un permiso
    # permission_required = ('catalogo.add_producto', 'catalogo.change_producto')  # Varios

    def handle_no_permission(self):
        """Personaliza la respuesta cuando el usuario no tiene permiso."""
        from django.contrib import messages
        messages.error(self.request, 'No tienes permiso para crear productos.')
        return super().handle_no_permission()

UserPassesTestMixin

Permite definir una función de prueba personalizada para autorizar el acceso:

from django.contrib.auth.mixins import UserPassesTestMixin
from django.views.generic.edit import UpdateView

class ProductoUpdateView(UserPassesTestMixin, UpdateView):
    model = Producto
    fields = ['nombre', 'precio']

    def test_func(self):
        """Solo el creador del producto o un admin puede editarlo."""
        producto = self.get_object()
        return self.request.user == producto.creado_por or self.request.user.is_staff

    def get_success_url(self):
        return reverse_lazy('producto-detail', kwargs={'pk': self.object.pk})

Combinar múltiples mixins

Los mixins se combinan con herencia múltiple. El orden importa: los primeros en la lista tienen prioridad en la resolución del método (MRO):

from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin

class GestionProductosView(LoginRequiredMixin, PermissionRequiredMixin, CreateView):
    model = Producto
    fields = ['nombre', 'precio', 'categoria']
    permission_required = 'catalogo.add_producto'
    login_url = '/login/'
    success_url = reverse_lazy('producto-list')

Decoradores para vistas funcionales

Los decoradores equivalentes para vistas funcionales son:

from django.contrib.auth.decorators import login_required, permission_required
from django.views.decorators.http import require_http_methods, require_GET, require_POST
from django.shortcuts import render, get_object_or_404
from .models import Producto

@login_required
def mis_favoritos(request):
    favoritos = request.user.favoritos.select_related('producto').all()
    return render(request, 'catalogo/favoritos.html', {'favoritos': favoritos})

@login_required
@permission_required('catalogo.add_producto', raise_exception=True)
def crear_producto(request):
    # Solo accesible para usuarios con permiso catalogo.add_producto
    ...

@require_http_methods(['GET', 'POST'])
def contacto(request):
    if request.method == 'POST':
        # Procesar formulario
        ...
    return render(request, 'contacto.html')

Aplicar decoradores a CBV

Para aplicar decoradores de funciones a vistas basadas en clases se usa method_decorator:

from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
from django.views.generic import TemplateView

@method_decorator(login_required, name='dispatch')
class DashboardView(TemplateView):
    template_name = 'dashboard.html'

# Equivalente con mixin (más idiomático)
class DashboardView(LoginRequiredMixin, TemplateView):
    template_name = 'dashboard.html'

Mixin personalizado

Es posible crear mixins propios para reutilizar comportamiento transversal:

class PropietarioMixin:
    """Mixin que filtra objetos por el usuario autenticado."""
    def get_queryset(self):
        return super().get_queryset().filter(creado_por=self.request.user)

class PropietarioEditMixin(PropietarioMixin):
    """Añade contexto con el nombre del propietario."""
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['propietario'] = self.request.user.get_full_name()
        return context

class MisOrdenesListView(LoginRequiredMixin, PropietarioMixin, ListView):
    model = Pedido
    template_name = 'pedidos/lista.html'

Los mixins y decoradores de Django permiten añadir control de acceso, validaciones y comportamiento transversal a las vistas de forma declarativa y reutilizable, siguiendo el principio DRY del framework.

Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Django

Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

Aplicar LoginRequiredMixin para requerir autenticación en vistas basadas en clases. Usar PermissionRequiredMixin para exigir permisos concretos a nivel de vista. Implementar UserPassesTestMixin para lógica de autorización personalizada. Combinar múltiples mixins con herencia múltiple en el orden correcto. Usar los decoradores @login_required y @permission_required en vistas funcionales.