
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 theMetaclass in your model and add apermissionslist 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
UserPassesTestMixinused 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.