drf-rules is a Django REST Framework extension built on top of
django-rules that provides object-level permissions fully aligned
with DRF actions.
It allows you to declaratively define which users or groups can perform each action (create, list, retrieve, update, destroy, etc.) on your models and API endpoints.
- Simplicity (KISS): minimal setup, easy to understand.
- Native DRF integration: rules map directly to DRF actions.
- Consistent conventions: follows DRF’s CRUD action names
(
retrieveinstead ofview,destroyinstead ofdelete). - Well tested and documented: high test coverage and clear examples.
- Powered by django-rules: inherits its flexibility and extensibility.
- Requirements
- Installation
- Django Setup
- Defining Rules
- Using with DRF + Model Permissions + View Permissions + Custom User Integration
- License
- Python 3.8+
- Django 4.2+
Note: drf-rules supports all currently maintained Django versions and drops end-of-life versions in minor releases. See the Django Project documentation for timelines.
Using pip:
$ pip install drf-rulesUsing uv:
$ uv add drf-rulesRun tests with:
$ ./runtests.shAdd rules to INSTALLED_APPS:
INSTALLED_APPS = [
# ...
"rules",
]Configure authentication backends:
AUTHENTICATION_BACKENDS = [
"rules.permissions.ObjectPermissionBackend",
"django.contrib.auth.backends.ModelBackend",
]Example with a Book model:
import rules
@rules.predicate
def is_librarian(user):
return user.groups.filter(name="librarians").exists()
@rules.predicate
def is_author(user):
return user.groups.filter(name="authors").exists()Define object-level rules in Meta.rules_permissions:
import rules
from rules.contrib.models import RulesModel
class Book(RulesModel):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
class Meta:
rules_permissions = {
"create": rules.is_staff,
"retrieve": rules.is_authenticated,
}CRUD conventions differ slightly:
| Action | django-rules | drf-rules |
|---|---|---|
| Create | add | create |
| Retrieve | view | retrieve |
| Update | change | update / partial_update |
| Delete | delete | destroy |
| List | view | list |
Use AutoRulesPermission with your DRF views:
from rest_framework.viewsets import ModelViewSet
from drf_rules.permissions import AutoRulesPermission
class BookViewSet(ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [AutoRulesPermission]You can also define rules for custom actions:
class Book(RulesModel):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
class Meta:
rules_permissions = {
"create": rules.is_staff,
"retrieve": rules.is_authenticated,
"custom_nodetail": rules.is_authenticated,
":default:": rules.is_authenticated,
}- The
:default:rule applies to all conventional actions (list,retrieve,create,update,partial_update,destroy) not explicitly defined. - Non-standard actions (e.g.
custom_nodetail) must be defined explicitly.
If you are using a custom User model or any other custom model, you can
integrate drf-rules by combining RulesModelMixin with the
RulesModelBase metaclass. This ensures that permissions are automatically
registered on the model.
from django.contrib.auth.models import AbstractUser
from rules.contrib.models import RulesModelMixin, RulesModelBase
class CustomUser(AbstractUser, RulesModelMixin, metaclass=RulesModelBase):
"""
Example custom user integrated with drf-rules.
You can define CRUD permissions here via Meta.rules_permissions.
"""
class Meta:
rules_permissions = {
"create": rules.is_staff,
"retrieve": rules.is_authenticated,
":default:": rules.is_authenticated,
}If you already use a custom metaclass for your user model (or any other
model), make sure it inherits from ``RulesModelBase`` so that
drf-rules can register permissions correctly.
drf-rules is distributed under the terms of the
BSD-3-Clause license.