The permission_required Decorator
In this page:
Requiring a Specific Permission
@permission_required takes a permission string in the form 'app_label.action_modelname', such as 'library.add_book'.
Example: Requiring a Specific Permission
Only users (or groups) granted the 'library.add_book' permission can reach this view; others get redirected.
from django.contrib.auth.decorators import permission_required
from django.shortcuts import render
@permission_required('library.add_book')
def add_book_view(request):
return render(request, 'add_book.html')
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
Returning 403 Instead of Redirecting
By default a denied user is redirected to LOGIN_URL. Setting raise_exception=True returns an HTTP 403 error page instead.
Example: Returning 403 Instead of Redirecting
raise_exception=True is useful when the user IS logged in but simply lacks the permission — a redirect to login would be misleading.
from django.contrib.auth.decorators import permission_required
@permission_required('library.delete_book', raise_exception=True)
def delete_book_view(request):
return delete_book(request)
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
Checking Permissions in Templates
Templates can hide or show links based on request.user.has_perm, matching the same permission string.
Example: Checking Permissions in Templates
has_perm() mirrors the decorator's check, so the link only appears for users who could actually use it.
{% if user.has_perm('library.add_book') %}
<a href="{% url 'add_book' %}">Add Book</a>
{% endif %}
{# Django-only code -- models.py/views.py/urls.py/settings.py
snippets, or template markup using Django template tags/variables
-- can't run standalone via Judge0 or the browser preview, since
it needs a real Django project. Only this course's pure-Python
examples (example_lang == 'python', no Django imports) are
actually runnable, so those still get the button below. #}
- Forgetting the app_label prefix in the permission string, e.g. writing add_book instead of 'library.add_book'.
- Assuming permission_required also checks login — it does, but only redirects, it doesn't tell the user WHY access was denied unless raise_exception is set.
- Granting is_superuser instead of the specific permission when only one narrow permission was actually needed.
- @permission_required checks a specific permission string like 'app_label.action_modelname'.
- By default it redirects unauthenticated or unauthorized users, just like login_required.
- raise_exception=True makes it return a 403 Forbidden instead of redirecting.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first:
- Introduction to Django's Auth System
- The User Model Overview
- Setting Up a Login View
- Logout Functionality
- User Registration Form
- The login_required Decorator
- The permission_required Decorator
- Django Groups and Permissions
- Password Hashing in Django
- Session Authentication Basics
- Introduction to Custom User Models
- Sending Emails with Django