SyntaxStudy
Sign Up
Django Permissions and Groups
Django Beginner 1 min read

Permissions and Groups

Django's permission system allows fine-grained access control. Django automatically creates four permissions for each model: add, change, delete, and view. You can also create custom permissions in a model's Meta class. Permissions are checked in views using request.user.has_perm('app_label.permission_codename') or in templates with the perms template variable. Groups are collections of permissions that can be assigned to multiple users at once. Instead of granting individual permissions to each user, you create groups like "editors" or "moderators", assign the appropriate permissions to those groups, and then add users to the relevant group. This makes permission management much more maintainable as teams grow. The @permission_required decorator (for FBVs) and PermissionRequiredMixin (for CBVs) protect views that require specific permissions. Both redirect unauthenticated users to the login page and, by default, raise a 403 Forbidden error for authenticated users who lack the required permission. Setting raise_exception=True makes the decorator raise a 403 instead of redirecting, which is more appropriate for API-style views or AJAX requests.
Example
# blog/models.py — custom permissions
class Post(models.Model):
    title  = models.CharField(max_length=200)
    body   = models.TextField()
    status = models.CharField(max_length=10, default='draft')

    class Meta:
        permissions = [
            ('publish_post',  'Can publish posts'),
            ('feature_post',  'Can feature posts on the homepage'),
        ]


# blog/views.py — permission_required decorator
from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin

@permission_required('blog.publish_post', raise_exception=True)
def publish_post(request, pk):
    post = get_object_or_404(Post, pk=pk)
    post.status = 'published'
    post.save()
    return redirect('blog:post-detail', pk=post.pk)


class PostCreateView(PermissionRequiredMixin, CreateView):
    permission_required = 'blog.add_post'
    model         = Post
    form_class    = PostForm
    template_name = 'blog/post_form.html'


# Creating groups and assigning permissions (e.g., in a management command)
from django.contrib.auth.models import Group, Permission

editors = Group.objects.get_or_create(name='Editors')[0]
publish_perm = Permission.objects.get(codename='publish_post')
editors.permissions.add(publish_perm)

# Assign user to group
user.groups.add(editors)

# Check in templates
# {% if perms.blog.publish_post %}
#     <a href="{% url 'blog:publish' pk=post.pk %}">Publish</a>
# {% endif %}