User Permissions - potatoscript/django GitHub Wiki
🛡️ Django User Permissions & Authorization
In this tutorial, we will dive into user permissions and authorization in Django. Understanding how to manage who can access what in your application is crucial for maintaining security. Django provides a robust permission system that allows you to control access to different parts of your website or application.
🗂️ Step 1: Understanding Permissions
Django’s authentication system is divided into two parts:
- Authentication – Who is the user? (Do they have an account?)
- Authorization – What can the user do? (Do they have permission to access this page?)
In Django, permissions are used to determine what a user can do. There are two types of permissions you need to understand:
- Model-level permissions – These permissions control who can add, change, or delete specific models in your application.
- Object-level permissions – These permissions are applied to specific objects in the database (such as a blog post or comment).
Django has a default set of permissions for each model:
add_modelname
change_modelname
delete_modelname
view_modelname
(in Django 2.1 and higher)
🧩 Step 2: Using Built-In Permissions
When you create a model, Django automatically provides a default set of permissions for that model. For example, let’s consider a Post
model.
# models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
def __str__(self):
return self.title
For this model, Django automatically creates the following permissions:
add_post
change_post
delete_post
view_post
These permissions are automatically added to the database when you run migrations.
🖼️ Example: Checking Permissions in Views
You can check if a user has specific permissions by using the user.has_perm()
method in your views.
# views.py
from django.shortcuts import render
from django.http import HttpResponseForbidden
from .models import Post
def post_detail(request, post_id):
post = Post.objects.get(id=post_id)
# Check if user has permission to view the post
if not request.user.has_perm('app.view_post'):
return HttpResponseForbidden("You do not have permission to view this post.")
return render(request, 'post_detail.html', {'post': post})
In this example, if the user doesn't have permission to view the post, they are denied access and an HTTP 403 Forbidden response is returned.
🧩 Step 3: Assigning Permissions to Users
To assign permissions, you can use Django’s built-in Groups or assign individual permissions directly to a user.
🖼️ Step 3.1: Using Django Admin to Assign Permissions
- Login to Django Admin: If you haven't already, create an admin user using the following command:
python manage.py createsuperuser
-
Assign Permissions to Groups:
- Go to the Django Admin site (
http://127.0.0.1:8000/admin/
). - In the Users section, select Groups.
- Create a new group and assign it permissions.
- Go to the Django Admin site (
-
Assign Permissions to Users:
- Go to the Users section, click on a user.
- In the Permissions section, check the boxes for the permissions you want to assign to the user.
🖼️ Step 3.2: Assign Permissions Programmatically
You can also assign permissions to users programmatically using Django's API.
# Assign permissions to a user programmatically
from django.contrib.auth.models import User, Permission
# Get the user and the permission
user = User.objects.get(username='john')
permission = Permission.objects.get(codename='change_post')
# Assign the permission to the user
user.user_permissions.add(permission)
🧩 Step 4: Using Custom Permissions
While Django provides default permissions like add
, change
, delete
, and view
, you might want to define custom permissions that fit the needs of your application.
🖼️ Step 4.1: Adding Custom Permissions to Models
You can define custom permissions by using the Meta
class within your model.
# models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
class Meta:
permissions = [
("can_publish_post", "Can publish post"),
]
def __str__(self):
return self.title
After adding the custom permission, run migrations:
python manage.py makemigrations
python manage.py migrate
This will create the permission can_publish_post
.
🧩 Step 5: Protecting Views with Permissions
You can use the @permission_required
decorator to restrict access to views based on specific permissions.
# views.py
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
from .models import Post
@permission_required('app.can_publish_post', raise_exception=True)
def publish_post(request, post_id):
post = Post.objects.get(id=post_id)
# Logic to publish the post
return render(request, 'publish_success.html', {'post': post})
In this case, only users with the can_publish_post
permission can access the publish_post
view. If they don’t have the permission, they’ll be redirected to the login page or shown an error.
🧩 Step 6: Using User Groups for Simplified Permission Management
Instead of manually assigning permissions to each user, you can organize users into groups, where each group has a specific set of permissions.
🖼️ Example: Creating and Assigning Groups
You can create a group and assign permissions to it in the Django admin, or programmatically like this:
# Create a group and assign permissions
from django.contrib.auth.models import Group, Permission
# Create the group
group, created = Group.objects.get_or_create(name='Editors')
# Get permissions and assign to group
permissions = Permission.objects.filter(codename__in=['change_post', 'can_publish_post'])
group.permissions.set(permissions)
Now, all users in the Editors
group will have the change_post
and can_publish_post
permissions.
🧩 Step 7: Handling Object-Level Permissions
Sometimes, you need permissions that apply to specific objects. Django doesn’t handle object-level permissions out of the box, but you can implement this by extending your logic with custom decorators or third-party libraries like django-guardian
.
For example, using django-guardian
:
-
Install the library:
pip install django-guardian
-
Define object-level permissions:
# models.py from guardian.models import UserObjectPermissionBase class PostPermission(UserObjectPermissionBase): content_object = models.ForeignKey(Post, on_delete=models.CASCADE)
-
Use
guardian
to check if a user has permissions for a specific object:from guardian.shortcuts import assign_perm, get_objects_for_user # Assign permission to user for a specific object assign_perm('can_publish_post', user, post) # Get posts the user can publish posts = get_objects_for_user(user, 'can_publish_post', klass=Post)
📝 Summary
Step | What Happens |
---|---|
1. Understanding Permissions | Learn about Django’s default and custom permissions system. |
2. Using Built-In Permissions | Use Django’s default model-level permissions to control access to views. |
3. Assigning Permissions | Learn how to assign permissions to users, either manually or through groups. |
4. Custom Permissions | Define and create custom permissions for more specific needs. |
5. Protecting Views | Protect views using the @permission_required decorator. |
6. Using Groups | Simplify permission management by assigning permissions to groups. |
7. Object-Level Permissions | Manage permissions for specific objects using third-party libraries like django-guardian . |