How to Work Model Level Permissions in Django?

Published On: 25/03/2025 | Category: Django
How to Work Model Level Permissions in Django - Tutorial

Hi Dev,

If you’re looking to learn how to implement model-level permissions in Django, you’ve landed at the right place. In this tutorial, we’ll walk through how to create and use custom model permissions using Django’s built-in features.

Permissions are essential when building secure and role-based access control systems in Django. Here, we’ll explore how to define and enforce custom permissions on a model using Django’s Meta class and UserPassesTestMixin.

This guide also briefly touches on Django’s groups and permissions structure and how you can utilize it effectively for your applications.

Model-level Permissions

You can add custom permissions to a Django model via the model’s Meta class. These permissions can then be checked in your views or templates.

Let’s say we add a boolean field is_published to a Post model:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=400)
    body = models.TextField()
    is_published = models.BooleanField(default=False)

Now let’s define a custom permission in the model’s Meta class:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=400)
    body = models.TextField()
    is_published = models.BooleanField(default=False)

    class Meta:
        permissions = [
            (
                "set_published_status",
                "Can set the status of the post to either publish or not"
            )
        ]

We’ve defined a custom permission called set_published_status. This permission can now be assigned to users or groups through the Django admin panel or programmatically.

To enforce this permission in a class-based view, we use Django's UserPassesTestMixin mixin.

from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import render
from django.views.generic import View

from blog.models import Post

class PostListView(UserPassesTestMixin, View):
    template_name = "post_details.html"

    def test_func(self):
        return self.request.user.has_perm("blog.set_published_status")

    def post(self, request, *args, **kwargs):
        post_id = request.POST.get('post_id')
        published_status = request.POST.get('published_status')

        if post_id:
            post = Post.objects.get(pk=post_id)
            post.is_published = bool(published_status)
            post.save()

        return render(request, self.template_name)

As shown above, the test_func() method validates whether the current user has the permission blog.set_published_status. If not, Django will return a 403 Forbidden error by default.

This is an effective way to restrict access to sensitive operations like updating the publication status of posts.

Happy Coding!


📌 FAQ - Model-Level Permissions in Django

  • Q: How do I define custom model permissions in Django?
    A: Use the Meta class in your model and add a permissions list of tuples: (codename, description).
  • Q: Where can I assign these permissions?
    A: You can assign them to users or groups in Django Admin under the Users/Groups section.
  • Q: How do I check if a user has a permission?
    A: Use user.has_perm('app_label.permission_codename').
  • Q: What is UserPassesTestMixin used for?
    A: It allows you to control access to class-based views by implementing a custom test via test_func().
  • Q: Can I use decorators instead of mixins for permissions?
    A: Yes, function-based views can use decorators like @permission_required.