Django Rules for Authorization
Rules provides an awesome, simple, and powerful authorization solution for Django applications, without relying on database configuration. It allows defining permissions as Python callables (predicates) and integrating them seamlessly into views, templates, and Django REST Framework. The current version is 3.5, and it maintains a steady release cadence, typically aligning with new Django versions.
Warnings
- breaking Version 3.0.0 dropped support for Python 2 and Django versions older than 2.2. If you are upgrading from `rules<3.0` ensure your project runs on Python 3 and Django >= 2.2.
- breaking Version 3.4.0 dropped support for Python 3.7 and Django 2.2 and 4.0. Future versions will continue to drop support for EOL Python and Django versions. Always check release notes when upgrading.
- gotcha For rules to function correctly with Django's system checks and to allow automatic rule discovery (e.g., via `rules.contrib.apps.RulesConfig`), you should add `rules` to your `INSTALLED_APPS`.
- gotcha When using `PermissionsRequiredMixin` or `AutoPermissionViewSetMixin`, remember to explicitly set the `permission_required` attribute on your class-based view or viewset to the string name of the rule.
Install
-
pip install rules
Imports
- rule
from rules import rule
- Predicate
from rules import Predicate
- is_authenticated
from rules.permissions import is_authenticated
- PermissionsRequiredMixin
from rules.contrib.views import PermissionsRequiredMixin
- AutoPermissionViewSetMixin
from rules.contrib.rest_framework import AutoPermissionViewSetMixin
Quickstart
import rules
from rules import Predicate
from django.conf import settings
from django.apps import apps
from django.http import HttpResponse
from django.views.generic import View
settings.configure(
INSTALLED_APPS=['django.contrib.auth', 'django.contrib.contenttypes', 'rules'],
SECRET_KEY='a-very-secret-key',
TEMPLATES=[{'BACKEND': 'django.template.backends.django.DjangoTemplates', 'OPTIONS': {'string_if_invalid': 'INVALID'}}],
DEBUG=True
)
apps.populate(settings.INSTALLED_APPS)
# 1. Define a simple predicate
is_staff = Predicate(lambda u: u.is_staff)
# 2. Add the rule with a name
rules.add_rule('can_access_staff_area', is_staff)
# 3. Use it in a Django View
from rules.contrib.views import PermissionsRequiredMixin
from django.contrib.auth.models import User
class StaffAreaView(PermissionsRequiredMixin, View):
permission_required = 'can_access_staff_area'
def get(self, request):
return HttpResponse("Welcome, staff member!")
# Example of creating a mock user and checking permission (for demonstration)
mock_user_staff = User(username='staffuser', is_staff=True)
mock_user_non_staff = User(username='regularuser', is_staff=False)
# This would typically happen inside a request context
can_access_staff_true = rules.test_rule('can_access_staff_area', mock_user_staff)
can_access_staff_false = rules.test_rule('can_access_staff_area', mock_user_non_staff)
assert can_access_staff_true is True
assert can_access_staff_false is False
print(f"Staff user can access staff area: {can_access_staff_true}")
print(f"Regular user can access staff area: {can_access_staff_false}")