Python > Web Development with Python > Django > Authentication and Authorization
Django Permission-Based Authorization
This snippet demonstrates how to implement permission-based authorization in Django. It covers defining custom permissions, assigning permissions to users and groups, and using the @permission_required
decorator to restrict access to views based on user permissions.
Concepts Behind the Snippet
Django's permission system provides a flexible way to control access to resources based on user permissions. Permissions are typically associated with models and represent specific actions a user can perform (e.g., add, change, delete). Permissions can be assigned directly to users or to groups, and users inherit the permissions of the groups they belong to. The @permission_required
decorator is a convenient way to enforce permission checks at the view level.
Defining Custom Permissions in a Model (models.py
in your app)
You can define custom permissions within your Django models using the Meta
class. Here's an example of defining permissions for a 'Article' model:
from django.db import models
class Article(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
class Meta:
permissions = [
('can_publish_article', 'Can publish article'),
('can_edit_article', 'Can edit article'),
]
Assigning Permissions to Users and Groups
Permissions can be assigned to users and groups through the Django admin interface. Go to the admin panel, select a user or group, and assign the desired permissions. You can also programmatically assign permissions using the Django ORM:
from django.contrib.auth.models import User, Group, Permission
from django.contrib.contenttypes.models import ContentType
from .models import Article
# Get the 'can_publish_article' permission
content_type = ContentType.objects.get_for_model(Article)
publish_permission = Permission.objects.get(codename='can_publish_article', content_type=content_type)
# Get a user and a group
user = User.objects.get(username='testuser')
group = Group.objects.get(name='editors')
# Assign the permission to the user
user.user_permissions.add(publish_permission)
# Assign the permission to the group
group.permissions.add(publish_permission)
# Save the user and the group
user.save()
group.save()
Using the @permission_required
Decorator
The @permission_required
decorator allows you to restrict access to views based on user permissions. If a user does not have the required permission, they will be redirected to a login page (or a 403 Forbidden page if they are already logged in).
from django.shortcuts import render
from django.contrib.auth.decorators import permission_required
@permission_required('accounts.can_publish_article') # Replace 'accounts' with your app name
def publish_article(request):
# Only users with the 'can_publish_article' permission can access this view
return render(request, 'accounts/publish_article.html')
Checking Permissions in Templates
You can also check for permissions directly within your Django templates using the perms
variable. This allows you to conditionally display content or functionality based on the user's permissions.
{% if perms.accounts.can_publish_article %}
<a href="{% url 'publish_article' %}">Publish Article</a>
{% else %}
<p>You do not have permission to publish articles.</p>
{% endif %}
Real-Life Use Case
Imagine a content management system (CMS) where different users have different roles. Administrators might have full access, editors can publish articles, and authors can only create drafts. Permission-based authorization allows you to enforce these roles and ensure that users only have access to the features and data they are authorized to access.
Best Practices
Interview Tip
Understand the difference between authentication and authorization. Authentication verifies the user's identity, while authorization determines what the user is allowed to do. Django's permission system is a core part of authorization, and it's important to understand how it works and how to use it effectively.
When to Use Them
Use Django's permission system when you need to control access to resources based on user roles and permissions. This is particularly useful for applications with multiple user roles and varying levels of access to data and functionality.
Alternatives
django-guardian
.django-role-permissions
provides more comprehensive RBAC implementation.
FAQ
-
My custom permissions are not showing up in the admin interface. What's wrong?
Make sure you have runpython manage.py makemigrations
andpython manage.py migrate
after defining your custom permissions in your model. This creates the necessary database entries for the permissions. -
How do I check if a user has a specific permission without using the
@permission_required
decorator?
You can use thehas_perm()
method on the user object. For example:user.has_perm('accounts.can_publish_article')
. This returnsTrue
if the user has the specified permission, andFalse
otherwise.