drf-rules
=========
.. image:: https://img.shields.io/pypi/v/drf-rules.svg
:target: https://pypi.org/project/drf-rules
:alt: PyPI - Version
.. image:: https://img.shields.io/pypi/pyversions/drf-rules.svg
:target: https://pypi.org/project/drf-rules
:alt: PyPI - Python Version
.. image:: https://coveralls.io/repos/github/lsaavedr/drf-rules/badge.svg
:target: https://coveralls.io/github/lsaavedr/drf-rules
:alt: Coverage Status
``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.
----
.. _django-rules: https://github.com/dfunckt/django-rules
Features
--------
- **Simplicity (KISS)**: minimal setup, easy to understand.
- **Native DRF integration**: rules map directly to DRF actions.
- **Consistent conventions**: follows DRF’s CRUD action names
(``retrieve`` instead of ``view``, ``destroy`` instead of ``delete``).
- **Well tested and documented**: high test coverage and clear examples.
- **Powered by django-rules**: inherits its flexibility and extensibility.
Table of Contents
-----------------
- `Requirements`_
- `Installation`_
- `Django Setup`_
- `Defining Rules`_
- `Using with DRF`_
+ `Model Permissions`_
+ `View Permissions`_
+ `Custom User Integration`_
- `License`_
Requirements
------------
- 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.
Installation
------------
Using pip:
.. code-block:: console
$ pip install drf-rules
Using uv:
.. code-block:: console
$ uv add drf-rules
Run tests with:
.. code-block:: console
$ ./runtests.sh
Django Setup
------------
Add ``rules`` to ``INSTALLED_APPS``:
.. code-block:: python
INSTALLED_APPS = [
# ...
"rules",
]
Configure authentication backends:
.. code-block:: python
AUTHENTICATION_BACKENDS = [
"rules.permissions.ObjectPermissionBackend",
"django.contrib.auth.backends.ModelBackend",
]
Defining Rules
--------------
Example with a ``Book`` model:
.. code-block:: python
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()
Using with DRF
--------------
Model Permissions
.................
Define object-level rules in ``Meta.rules_permissions``:
.. code-block:: python
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:
.. list-table:: CRUD Conventions
:header-rows: 1
* - Action
- django-rules
- drf-rules
* - Create
- add
- create
* - Retrieve
- view
- retrieve
* - Update
- change
- update / partial_update
* - Delete
- delete
- destroy
* - List
- view
- list
View Permissions
................
Use ``AutoRulesPermission`` with your DRF views:
.. code-block:: python
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**:
.. code-block:: python
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.
Custom User Integration
.......................
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.
.. code-block:: python
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.
License
-------
``drf-rules`` is distributed under the terms of the
`BSD-3-Clause <https://spdx.org/licenses/BSD-3-Clause.html>`_ license.
Raw data
{
"_id": null,
"home_page": null,
"name": "drf-rules",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "django, drf, permissions, rules",
"author": null,
"author_email": "Luis Saavedra <luis94855510@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/72/83/000083a0a2c5644d819de7c6e613414c472ab8885ea614a628efd7939cb1/drf_rules-0.0.7.tar.gz",
"platform": null,
"description": "drf-rules\n=========\n\n.. image:: https://img.shields.io/pypi/v/drf-rules.svg\n :target: https://pypi.org/project/drf-rules\n :alt: PyPI - Version\n\n.. image:: https://img.shields.io/pypi/pyversions/drf-rules.svg\n :target: https://pypi.org/project/drf-rules\n :alt: PyPI - Python Version\n\n.. image:: https://coveralls.io/repos/github/lsaavedr/drf-rules/badge.svg\n :target: https://coveralls.io/github/lsaavedr/drf-rules\n :alt: Coverage Status\n\n``drf-rules`` is a **Django REST Framework** extension built on top of\n`django-rules`_ that provides **object-level permissions** fully aligned\nwith DRF actions.\n\nIt allows you to **declaratively define** which users or groups can perform\neach action (*create, list, retrieve, update, destroy, etc.*) on your models\nand API endpoints.\n\n----\n\n.. _django-rules: https://github.com/dfunckt/django-rules\n\n\nFeatures\n--------\n\n- **Simplicity (KISS)**: minimal setup, easy to understand.\n- **Native DRF integration**: rules map directly to DRF actions.\n- **Consistent conventions**: follows DRF\u2019s CRUD action names\n (``retrieve`` instead of ``view``, ``destroy`` instead of ``delete``).\n- **Well tested and documented**: high test coverage and clear examples.\n- **Powered by django-rules**: inherits its flexibility and extensibility.\n\n\nTable of Contents\n-----------------\n\n- `Requirements`_\n- `Installation`_\n- `Django Setup`_\n- `Defining Rules`_\n- `Using with DRF`_\n + `Model Permissions`_\n + `View Permissions`_\n + `Custom User Integration`_\n- `License`_\n\n\nRequirements\n------------\n\n- Python **3.8+**\n- Django **4.2+**\n\nNote: `drf-rules` supports all currently maintained Django versions and drops\nend-of-life versions in minor releases. See the Django Project documentation\nfor timelines.\n\n\nInstallation\n------------\n\nUsing pip:\n\n.. code-block:: console\n\n $ pip install drf-rules\n\nUsing uv:\n\n.. code-block:: console\n\n $ uv add drf-rules\n\nRun tests with:\n\n.. code-block:: console\n\n $ ./runtests.sh\n\n\nDjango Setup\n------------\n\nAdd ``rules`` to ``INSTALLED_APPS``:\n\n.. code-block:: python\n\n INSTALLED_APPS = [\n # ...\n \"rules\",\n ]\n\nConfigure authentication backends:\n\n.. code-block:: python\n\n AUTHENTICATION_BACKENDS = [\n \"rules.permissions.ObjectPermissionBackend\",\n \"django.contrib.auth.backends.ModelBackend\",\n ]\n\n\nDefining Rules\n--------------\n\nExample with a ``Book`` model:\n\n.. code-block:: python\n\n import rules\n\n @rules.predicate\n def is_librarian(user):\n return user.groups.filter(name=\"librarians\").exists()\n\n @rules.predicate\n def is_author(user):\n return user.groups.filter(name=\"authors\").exists()\n\n\nUsing with DRF\n--------------\n\nModel Permissions\n.................\n\nDefine object-level rules in ``Meta.rules_permissions``:\n\n.. code-block:: python\n\n import rules\n from rules.contrib.models import RulesModel\n\n class Book(RulesModel):\n title = models.CharField(max_length=100)\n author = models.CharField(max_length=100)\n\n class Meta:\n rules_permissions = {\n \"create\": rules.is_staff,\n \"retrieve\": rules.is_authenticated,\n }\n\nCRUD conventions differ slightly:\n\n.. list-table:: CRUD Conventions\n :header-rows: 1\n\n * - Action\n - django-rules\n - drf-rules\n * - Create\n - add\n - create\n * - Retrieve\n - view\n - retrieve\n * - Update\n - change\n - update / partial_update\n * - Delete\n - delete\n - destroy\n * - List\n - view\n - list\n\n\nView Permissions\n................\n\nUse ``AutoRulesPermission`` with your DRF views:\n\n.. code-block:: python\n\n from rest_framework.viewsets import ModelViewSet\n from drf_rules.permissions import AutoRulesPermission\n\n class BookViewSet(ModelViewSet):\n queryset = Book.objects.all()\n serializer_class = BookSerializer\n permission_classes = [AutoRulesPermission]\n\nYou can also define rules for **custom actions**:\n\n.. code-block:: python\n\n class Book(RulesModel):\n title = models.CharField(max_length=100)\n author = models.CharField(max_length=100)\n\n class Meta:\n rules_permissions = {\n \"create\": rules.is_staff,\n \"retrieve\": rules.is_authenticated,\n \"custom_nodetail\": rules.is_authenticated,\n \":default:\": rules.is_authenticated,\n }\n\n- The ``:default:`` rule applies to all **conventional** actions\n (``list``, ``retrieve``, ``create``, ``update``, ``partial_update``,\n ``destroy``) not explicitly defined.\n- Non-standard actions (e.g. ``custom_nodetail``) must be defined explicitly.\n\n\nCustom User Integration\n.......................\n\nIf you are using a **custom User model** or any other custom model, you can\nintegrate ``drf-rules`` by combining ``RulesModelMixin`` with the\n``RulesModelBase`` metaclass. This ensures that permissions are automatically\nregistered on the model.\n\n.. code-block:: python\n\n from django.contrib.auth.models import AbstractUser\n from rules.contrib.models import RulesModelMixin, RulesModelBase\n\n class CustomUser(AbstractUser, RulesModelMixin, metaclass=RulesModelBase):\n \"\"\"\n Example custom user integrated with drf-rules.\n You can define CRUD permissions here via Meta.rules_permissions.\n \"\"\"\n class Meta:\n rules_permissions = {\n \"create\": rules.is_staff,\n \"retrieve\": rules.is_authenticated,\n \":default:\": rules.is_authenticated,\n }\n\nIf you already use a **custom metaclass** for your user model (or any other\nmodel), make sure it **inherits from ``RulesModelBase``** so that\n``drf-rules`` can register permissions correctly.\n\n\nLicense\n-------\n\n``drf-rules`` is distributed under the terms of the\n`BSD-3-Clause <https://spdx.org/licenses/BSD-3-Clause.html>`_ license.\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Rules Permissions with Django DRF",
"version": "0.0.7",
"project_urls": {
"Documentation": "https://github.com/lsaavedr/drf-rules#readme",
"Issues": "https://github.com/lsaavedr/drf-rules/issues",
"Source": "https://github.com/lsaavedr/drf-rules"
},
"split_keywords": [
"django",
" drf",
" permissions",
" rules"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "86ff307fb48a8280881c0eb15272f75dcc715888a57aae35885739d15e101ad0",
"md5": "449fe906c96d7aee8674275016adacc5",
"sha256": "cad26bd2adae930c66f2dcb680fbb848d0c33ff4e2fe0181bb666915d926d9a6"
},
"downloads": -1,
"filename": "drf_rules-0.0.7-py3-none-any.whl",
"has_sig": false,
"md5_digest": "449fe906c96d7aee8674275016adacc5",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 7853,
"upload_time": "2025-09-13T22:33:15",
"upload_time_iso_8601": "2025-09-13T22:33:15.084279Z",
"url": "https://files.pythonhosted.org/packages/86/ff/307fb48a8280881c0eb15272f75dcc715888a57aae35885739d15e101ad0/drf_rules-0.0.7-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "7283000083a0a2c5644d819de7c6e613414c472ab8885ea614a628efd7939cb1",
"md5": "778d0c0f19442db132f2c57fa4bad2f8",
"sha256": "4a737b80e6315265a1d38ae432b57e2c9f3ddbdea5e0f75864c3a12839f8b99e"
},
"downloads": -1,
"filename": "drf_rules-0.0.7.tar.gz",
"has_sig": false,
"md5_digest": "778d0c0f19442db132f2c57fa4bad2f8",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 37871,
"upload_time": "2025-09-13T22:33:16",
"upload_time_iso_8601": "2025-09-13T22:33:16.636970Z",
"url": "https://files.pythonhosted.org/packages/72/83/000083a0a2c5644d819de7c6e613414c472ab8885ea614a628efd7939cb1/drf_rules-0.0.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-13 22:33:16",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "lsaavedr",
"github_project": "drf-rules#readme",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "drf-rules"
}