Django Authentication and Permissions
TL;DR
Django provides a complete authentication and authorization sub-system out of the box. Use @login_required to restrict views to authenticated users and @permission_required to enforce granular access control based on custom permissions defined in your models.
Interesting!
Django automatically creates four default permissions for every model (add, change, delete, view) during migrations, but you can define custom permissions in your model’s Meta class to implement fine-grained authorization for any business logic you need.
The Authentication Foundation
Django’s authentication system lives in django.contrib.auth and works seamlessly with sessions via middleware. The @login_required decorator enforces authentication checks:
python code snippet start
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
# Only authenticated users can access this view
return render(request, 'template.html')python code snippet end
When an unauthenticated user tries to access a protected view, Django redirects them to the login page (defined by settings.LOGIN_URL) and stores the original URL in a “next” query parameter so they can be redirected back after login.
Custom Permissions in Models
You can define custom permissions in your model’s Meta class. These permissions use the format <app_label>.<permission_codename>:
python code snippet start
from django.db import models
class Shape(models.Model):
color = models.CharField(max_length=10)
shape_type = models.CharField(max_length=10)
class Meta:
permissions = [
("view_shapes_canvas", "Can view the shapes canvas"),
("add_red_shape", "Can add red shapes"),
("add_green_shape", "Can add green shapes"),
("add_blue_shape", "Can add blue shapes"),
]python code snippet end
These custom permissions appear in the Django admin interface and can be assigned to individual users or groups.
The @permission_required Decorator
The @permission_required decorator enforces authorization checks before allowing view access:
python code snippet start
from django.contrib.auth.decorators import permission_required
@login_required
@permission_required('shapes.view_shapes_canvas', raise_exception=True)
def canvas_view(request):
# Only users with 'view_shapes_canvas' permission can access
return render(request, 'canvas.html')python code snippet end
Setting raise_exception=True returns a 403 Forbidden response instead of redirecting to the login page. You can also pass multiple permissions as a list when a view requires several permissions.
Checking Permissions Programmatically
Use request.user.has_perm() to check permissions within your views:
python code snippet start
@login_required
def add_shape(request):
color = request.POST.get('color')
# Check permission based on color
if color == 'red' and not request.user.has_perm('shapes.add_red_shape'):
messages.error(request, "You don't have permission to add red shapes!")
return redirect('canvas')
# Permission granted, create the shape
Shape.objects.create(color=color, ...)python code snippet end
This pattern lets you implement authorization logic beyond simple built-in object-based checks.
Dynamic Permission-Based UI
Pass permission checks to your templates to enable or disable UI elements:
python code snippet start
context = {
'can_add_red': request.user.has_perm('shapes.add_red_shape'),
'can_add_green': request.user.has_perm('shapes.add_green_shape'),
'can_delete': request.user.has_perm('shapes.delete_shape'),
}
return render(request, 'canvas.html', context)python code snippet end
In your template:
html code snippet start
<button {% if not can_add_red %}disabled{% endif %}>
Add Red Shape
</button>html code snippet end
Automatic Permission Creation
Django automatically creates four permissions for each model during migrations: add_<modelname>, change_<modelname>, delete_<modelname>, and view_<modelname>. These are available immediately after running python manage.py migrate, assuming django.contrib.auth is in your INSTALLED_APPS.
Summary
This demonstrates how Django’s permission system enables fine-grained access control for any application logic, not just CRUD operations.
Django’s built-in authentication and permissions system provides everything you need to implement secure, granular authorization without reaching for third-party packages. The combination of decorators, programmatic checks, and custom permissions makes it straightforward to build applications with complex access control requirements.
Django’s decorator-based authentication builds on Python’s decorator patterns from functools . The permission system integrates naturally with Python classes through model definitions. Understanding function annotations helps when working with Django’s type-aware tools and modern API frameworks.
Reference: Django Authentication System