How to Work Model Level Permissions in Django?

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 theMeta
class in your model and add apermissions
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: Useuser.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 viatest_func()
. - Q: Can I use decorators instead of mixins for permissions?
A: Yes, function-based views can use decorators like@permission_required
.