Acciones personalizadas en el admin Django

Intermedio
Django
Django
Actualizado: 18/04/2026

Qué son las acciones de admin

Las acciones de admin aparecen en el menú desplegable del listado de modelos y permiten ejecutar operaciones sobre los registros seleccionados. Django incluye delete_selected por defecto.

Diagrama conceptual de Acciones personalizadas en el admin Django

Acción simple: publicar/archivar

from django.contrib import admin, messages
from django.utils.translation import ngettext

@admin.register(Articulo)
class ArticuloAdmin(admin.ModelAdmin):
    list_display = ['titulo', 'publicado', 'autor', 'fecha_creacion']
    actions = ['publicar_articulos', 'archivar_articulos']

    @admin.action(description='Publicar artículos seleccionados')
    def publicar_articulos(self, request, queryset):
        actualizados = queryset.update(publicado=True)
        self.message_user(
            request,
            ngettext(
                '%d artículo publicado correctamente.',
                '%d artículos publicados correctamente.',
                actualizados
            ) % actualizados,
            messages.SUCCESS
        )

    @admin.action(description='Archivar artículos seleccionados')
    def archivar_articulos(self, request, queryset):
        actualizados = queryset.update(publicado=False, archivado=True)
        self.message_user(request, f'{actualizados} artículo(s) archivado(s).', messages.WARNING)

Exportar a CSV

import csv
from django.http import HttpResponse
from django.contrib import admin

@admin.register(Pedido)
class PedidoAdmin(admin.ModelAdmin):
    actions = ['exportar_csv']

    @admin.action(description='Exportar seleccionados a CSV')
    def exportar_csv(self, request, queryset):
        response = HttpResponse(content_type='text/csv; charset=utf-8')
        response['Content-Disposition'] = 'attachment; filename="pedidos.csv"'
        response.write('\ufeff')  # BOM para Excel

        writer = csv.writer(response)
        writer.writerow(['ID', 'Cliente', 'Estado', 'Total', 'Fecha'])

        for pedido in queryset.select_related('cliente'):
            writer.writerow([
                pedido.id,
                pedido.cliente.get_full_name(),
                pedido.get_estado_display(),
                pedido.total,
                pedido.fecha_creacion.strftime('%d/%m/%Y %H:%M'),
            ])

        self.message_user(request, f'{queryset.count()} pedido(s) exportado(s).')
        return response

Acción con confirmación (dos pasos)

Para acciones críticas, implementa un flujo de confirmación:

from django.shortcuts import render
from django.contrib import admin

@admin.register(Usuario)
class UsuarioAdmin(admin.ModelAdmin):
    actions = ['desactivar_usuarios']

    @admin.action(description='Desactivar cuentas de usuario seleccionadas')
    def desactivar_usuarios(self, request, queryset):
        # Si el formulario de confirmación ya fue enviado
        if 'confirmar' in request.POST:
            queryset.update(is_active=False)
            self.message_user(
                request,
                f'{queryset.count()} cuenta(s) desactivada(s).',
                messages.SUCCESS
            )
            return None

        # Mostrar formulario de confirmación
        return render(request, 'admin/confirmar_desactivar.html', {
            'titulo': 'Confirmar desactivación',
            'usuarios': queryset,
            'action': 'desactivar_usuarios',
        })
<!-- templates/admin/confirmar_desactivar.html -->
{% extends "admin/base_site.html" %}
{% block content %}
<h2>{{ titulo }}</h2>
<p>¿Estás seguro de que quieres desactivar las siguientes cuentas?</p>
<ul>
    {% for usuario in usuarios %}
        <li>{{ usuario.username }} ({{ usuario.email }})</li>
    {% endfor %}
</ul>
<form method="post">
    {% csrf_token %}
    {% for usuario in usuarios %}
        <input type="hidden" name="_selected_action" value="{{ usuario.pk }}">
    {% endfor %}
    <input type="hidden" name="action" value="{{ action }}">
    <button type="submit" name="confirmar">Sí, desactivar</button>
    <a href="..">Cancelar</a>
</form>
{% endblock %}

Acciones con permisos

@admin.action(description='Exportar datos sensibles')
def exportar_datos_sensibles(modeladmin, request, queryset):
    if not request.user.has_perm('app.exportar_datos'):
        modeladmin.message_user(request, 'Sin permiso para exportar.', messages.ERROR)
        return
    # ... lógica de exportación
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

Crear acciones de admin para operar en lote sobre registros seleccionados. Registrar acciones en el atributo actions de ModelAdmin. Implementar acciones que exportan datos a CSV. Añadir confirmación antes de ejecutar acciones destructivas. Usar messages para informar al usuario del resultado de la acción.