Permisos y grupos en Django

Intermedio
Django
Django
Actualizado: 18/04/2026

Permisos automáticos por modelo

Django genera automáticamente cuatro permisos para cada modelo registrado:

  • app.add_modelo: puede crear instancias
  • app.change_modelo: puede modificar instancias
  • app.delete_modelo: puede eliminar instancias
  • app.view_modelo: puede ver instancias (desde Django 2.1)
usuario = User.objects.get(username='ana')

# Verificar un permiso
usuario.has_perm('catalogo.add_producto')   # True o False

# Verificar varios permisos a la vez
usuario.has_perms(['catalogo.add_producto', 'catalogo.change_producto'])

# Permisos del usuario (cachedos en la sesión)
usuario.get_all_permissions()  # Conjunto de todos sus permisos

Diagrama conceptual de Permisos y grupos en Django

Permisos personalizados

Para operaciones que van más allá del CRUD básico, define permisos adicionales en la clase Meta:

# models.py
class Articulo(models.Model):
    titulo = models.CharField(max_length=200)
    contenido = models.TextField()
    publicado = models.BooleanField(default=False)
    autor = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

    class Meta:
        permissions = [
            ('publicar_articulo', 'Puede publicar artículos'),
            ('destacar_articulo', 'Puede destacar artículos en portada'),
            ('moderar_comentarios', 'Puede moderar comentarios de los artículos'),
        ]

Después de ejecutar makemigrations y migrate, los permisos estarán disponibles:

usuario.has_perm('blog.publicar_articulo')

Grupos de permisos

Los grupos permiten asignar conjuntos de permisos a múltiples usuarios de forma eficiente, implementando el concepto de roles:

from django.contrib.auth.models import Group, Permission

# Crear grupos de roles
def crear_grupos_iniciales():
    # Grupo Editor
    editor, _ = Group.objects.get_or_create(name='Editor')
    permisos_editor = Permission.objects.filter(
        codename__in=['add_articulo', 'change_articulo', 'view_articulo']
    )
    editor.permissions.set(permisos_editor)

    # Grupo Redactor Jefe
    redactor_jefe, _ = Group.objects.get_or_create(name='Redactor Jefe')
    permisos_rj = Permission.objects.filter(
        codename__in=['add_articulo', 'change_articulo', 'delete_articulo',
                      'view_articulo', 'publicar_articulo', 'destacar_articulo']
    )
    redactor_jefe.permissions.set(permisos_rj)

    # Grupo Moderador
    moderador, _ = Group.objects.get_or_create(name='Moderador')
    permisos_mod = Permission.objects.filter(codename='moderar_comentarios')
    moderador.permissions.set(permisos_mod)

# Asignar usuario a un grupo
usuario = User.objects.get(username='ana')
grupo_editor = Group.objects.get(name='Editor')
usuario.groups.add(grupo_editor)

# Quitar usuario de un grupo
usuario.groups.remove(grupo_editor)

# Verificar si el usuario está en un grupo
usuario.groups.filter(name='Editor').exists()

Verificar permisos en vistas y plantillas

# En vistas funcionales
from django.contrib.auth.decorators import permission_required

@permission_required('blog.publicar_articulo', raise_exception=True)
def publicar_articulo(request, pk):
    articulo = get_object_or_404(Articulo, pk=pk)
    articulo.publicado = True
    articulo.save()
    return redirect('articulo-detail', pk=pk)

# En vistas basadas en clases
from django.contrib.auth.mixins import PermissionRequiredMixin

class PublicarArticuloView(PermissionRequiredMixin, UpdateView):
    permission_required = 'blog.publicar_articulo'
    model = Articulo
    fields = ['publicado']
<!-- En plantillas -->
{% if perms.blog.publicar_articulo %}
    <a href="{% url 'publicar-articulo' articulo.pk %}">Publicar</a>
{% endif %}

{% if perms.catalogo.add_producto %}
    <a href="{% url 'producto-create' %}">Nuevo producto</a>
{% endif %}

<!-- Verificar permisos múltiples -->
{% if user.is_staff or perms.blog.moderar_comentarios %}
    <div class="panel-moderacion">...</div>
{% endif %}

Permisos a nivel de objeto

Para permisos que dependen del objeto específico (ej.: solo el autor puede editar su artículo), Django ofrece ObjectPermissión a través de backends personalizados. La librería django-guardian es la solución más popular:

pip install django-guardian
# settings.py
AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'guardian.backends.ObjectPermissionBackend',
]
INSTALLED_APPS += ['guardian']

# Asignar permiso de objeto
from guardian.shortcuts import assign_perm, remove_perm, get_users_with_perms

assign_perm('change_articulo', usuario, articulo)     # Usuario puede editar este articulo
assign_perm('delete_articulo', grupo_admin, articulo) # Grupo puede eliminar este articulo

# Verificar
usuario.has_perm('change_articulo', articulo)  # True solo para este articulo
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

Comprender los permisos automáticos de Django por modelo (add, change, delete, view). Crear permisos personalizados en la clase Meta del modelo. Asignar y revocar permisos a usuarios individuales y grupos. Verificar permisos con has_perm() y user.has_perms(). Crear grupos de permisos para gestionar roles de usuario.