Skip to main content

API Reference

Complete API documentation for Django RLS.

Models

RLSModel

Base class for models that use Row Level Security.

from django_rls.models import RLSModel

class MyModel(RLSModel):
# Your fields here

class Meta:
rls_policies = [
# List of policies
]

Class Methods:

  • enable_rls() - Enable RLS for this model
  • disable_rls() - Disable RLS for this model
  • get_rls_policies() - Get list of policies defined for this model

Meta Options:

  • rls_policies - List of policy instances to apply to this model

Policies

BasePolicy

Abstract base class for all policies.

from django_rls.policies import BasePolicy

class CustomPolicy(BasePolicy):
def get_sql_expression(self) -> str:
return "your SQL expression"

Parameters:

  • name (str) - Unique name for the policy
  • operation (str) - SQL operation: 'ALL', 'SELECT', 'INSERT', 'UPDATE', 'DELETE'
  • permissive (bool) - Whether policy is permissive (True) or restrictive (False)
  • roles (str) - PostgreSQL roles to apply to (default: 'public')

UserPolicy

Policy for user-based access control.

from django_rls.policies import UserPolicy

UserPolicy(
name='owner_policy',
user_field='owner', # Foreign key field name
operation='ALL',
permissive=True
)

Parameters:

  • name (str) - Policy name
  • user_field (str) - Name of the foreign key field to User model
  • operation (str) - SQL operation (default: 'ALL')
  • permissive (bool) - Policy type (default: True)

TenantPolicy

Policy for tenant-based isolation.

from django_rls.policies import TenantPolicy

TenantPolicy(
name='tenant_isolation',
tenant_field='tenant', # Foreign key field name
operation='ALL',
permissive=False # Often restrictive for tenant isolation
)

Parameters:

  • name (str) - Policy name
  • tenant_field (str) - Name of the foreign key field to tenant model
  • operation (str) - SQL operation (default: 'ALL')
  • permissive (bool) - Policy type (default: True)

CustomPolicy

Policy with custom SQL expression.

from django_rls.policies import CustomPolicy

CustomPolicy(
name='complex_policy',
expression="status = 'active' AND (is_public OR owner_id = current_setting('rls.user_id')::int)"
)

Parameters:

  • name (str) - Policy name
  • expression (str) - SQL boolean expression
  • operation (str) - SQL operation (default: 'ALL')
  • permissive (bool) - Policy type (default: True)

Middleware

RLSContextMiddleware

Middleware that sets PostgreSQL session variables from request.

MIDDLEWARE = [
# ... other middleware
'django_rls.middleware.RLSContextMiddleware',
]

Behavior:

  • Extracts user ID from request.user
  • Extracts tenant ID from request.tenant, request.user.profile.tenant_id, or request.session['tenant_id']
  • Sets PostgreSQL session variables using SET LOCAL
  • Clears context after request

Customization:

from django_rls.middleware import RLSContextMiddleware

class CustomRLSMiddleware(RLSContextMiddleware):
def _get_tenant_id(self, request):
# Custom tenant extraction logic
return tenant_id

def _set_rls_context(self, request):
super()._set_rls_context(request)
# Set additional context

Database Functions

set_rls_context

Set a PostgreSQL session variable for RLS.

from django_rls.db.functions import set_rls_context

set_rls_context('user_id', 123)
set_rls_context('tenant_id', 456)
set_rls_context('custom_var', 'value', is_local=True)

Parameters:

  • name (str) - Variable name (without 'rls.' prefix)
  • value (Any) - Variable value
  • is_local (bool) - Use SET LOCAL (transaction-scoped) vs SET (session-scoped)

get_rls_context

Get a PostgreSQL session variable value.

from django_rls.db.functions import get_rls_context

user_id = get_rls_context('user_id')
tenant_id = get_rls_context('tenant_id', default=None)

Parameters:

  • name (str) - Variable name (without 'rls.' prefix)
  • default (Any) - Default value if variable not set

RLSContext

Context manager for temporarily setting RLS context.

from django_rls.db.functions import RLSContext

with RLSContext(user_id=123, tenant_id=456):
# Code executed with this context
documents = Document.objects.all()
# Context automatically cleared

Schema Editor

RLSDatabaseSchemaEditor

Extended schema editor with RLS operations.

from django_rls.backends.postgresql import RLSDatabaseSchemaEditor

with connection.schema_editor() as schema_editor:
schema_editor.enable_rls(Model)
schema_editor.create_policy(Model, policy)

Methods:

  • enable_rls(model) - Enable RLS on model's table
  • disable_rls(model) - Disable RLS on model's table
  • force_rls(model) - Force RLS (even for table owner)
  • create_policy(model, policy) - Create a policy
  • drop_policy(model, policy_name) - Drop a policy
  • alter_policy(model, policy) - Alter existing policy

Migration Operations

EnableRLS

Migration operation to enable RLS.

from django_rls.migration_operations import EnableRLS

operations = [
EnableRLS('myapp', 'MyModel'),
]

DisableRLS

Migration operation to disable RLS.

from django_rls.migration_operations import DisableRLS

operations = [
DisableRLS('myapp', 'MyModel'),
]

CreatePolicy

Migration operation to create a policy.

from django_rls.migration_operations import CreatePolicy
from django_rls.policies import UserPolicy

operations = [
CreatePolicy(
'myapp',
'MyModel',
UserPolicy('owner_policy', user_field='owner')
),
]

DropPolicy

Migration operation to drop a policy.

from django_rls.migration_operations import DropPolicy

operations = [
DropPolicy('myapp', 'MyModel', 'policy_name'),
]

Exceptions

PolicyError

Raised when policy configuration is invalid.

from django_rls.exceptions import PolicyError

try:
policy = UserPolicy('invalid_policy', user_field='')
except PolicyError as e:
print(f"Invalid policy: {e}")

ConfigurationError

Raised when RLS configuration is invalid.

from django_rls.exceptions import ConfigurationError

try:
class BadModel(RLSModel):
class Meta:
rls_policies = "not_a_list" # Should be a list
except ConfigurationError as e:
print(f"Configuration error: {e}")

Test Utilities

RLSTestMixin

Mixin providing RLS testing utilities.

from django_rls.test import RLSTestMixin
from django.test import TestCase

class MyTest(RLSTestMixin, TestCase):
def test_something(self):
with self.disable_rls(Model):
# Test with RLS disabled

with self.as_user(user):
# Test with specific user context

with self.with_context(user_id=1, tenant_id=2):
# Test with custom context

Methods:

  • disable_rls(model) - Context manager to temporarily disable RLS
  • as_user(user) - Context manager to set user context
  • with_context(**kwargs) - Context manager to set arbitrary context

Settings

DJANGO_RLS

Optional settings dict for Django RLS configuration.

DJANGO_RLS = {
'DEFAULT_SCHEMA_EDITOR': 'django_rls.backends.postgresql.RLSDatabaseSchemaEditor',
'CONTEXT_PROCESSOR': 'myapp.rls.custom_context_processor',
'AUTO_ENABLE_RLS': True, # Enable RLS automatically in migrations
'POLICY_NAMING_CONVENTION': '{model_name}_{policy_type}_policy',
}

Signals

pre_enable_rls

Sent before enabling RLS on a model.

from django_rls.signals import pre_enable_rls

@receiver(pre_enable_rls)
def before_enable_rls(sender, model, **kwargs):
print(f"About to enable RLS for {model}")

post_enable_rls

Sent after enabling RLS on a model.

from django_rls.signals import post_enable_rls

@receiver(post_enable_rls)
def after_enable_rls(sender, model, **kwargs):
print(f"RLS enabled for {model}")