CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-django-braces

Reusable, generic mixins for Django class-based views

Pending
Overview
Eval results
Files

access-control.mddocs/

Access Control and Authentication

Comprehensive authentication and authorization mixins for Django class-based views. These mixins provide fine-grained access control, from simple login requirements to complex permission checking and secure connection enforcement.

Capabilities

Common Access Control Attributes

All access control mixins inherit common functionality for login redirects and permission handling. These attributes are available on all access mixins:

  • login_url = None - URL to redirect to for login (defaults to settings.LOGIN_URL)
  • raise_exception = False - Whether to raise PermissionDenied or redirect
  • redirect_field_name = 'next' - Field name for storing redirect URL
  • redirect_unauthenticated_users = False - Special handling for unauthenticated users

Common methods available on access mixins:

  • get_login_url() - Get the login URL (can be overridden)
  • get_redirect_field_name() - Get redirect field name (can be overridden)
  • handle_no_permission(request) - Handle permission failures
  • no_permissions_fail(request) - Default failure handler (redirects to login)

User Authentication

Require user authentication with flexible redirect handling.

class LoginRequiredMixin(AccessMixin):
    """Requires the user to be authenticated"""
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate method after checking authentication"""

Usage example:

from django.views.generic import ListView
from braces.views import LoginRequiredMixin

class ProtectedListView(LoginRequiredMixin, ListView):
    model = MyModel
    login_url = '/accounts/login/'
    redirect_field_name = 'next'
    raise_exception = False  # Redirect instead of 403

Anonymous User Requirement

Require user to be unauthenticated, useful for login/register pages.

class AnonymousRequiredMixin(AccessMixin):
    """Requires the user to be unauthenticated"""
    authenticated_redirect_url = '/accounts/profile/'
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler after guaranteeing anonymity"""
        
    def get_authenticated_redirect_url(self):
        """Return the reversed authenticated redirect url"""

Usage example:

from django.views.generic import TemplateView
from braces.views import AnonymousRequiredMixin

class LoginPageView(AnonymousRequiredMixin, TemplateView):
    template_name = 'registration/login.html'
    authenticated_redirect_url = '/dashboard/'

Permission-Based Access

Require specific Django permissions before granting access.

class PermissionRequiredMixin(AccessMixin):
    """Requires user to have specific permission(s)"""
    permission_required = None
    object_level_permissions = False
    
    def get_permission_required(self, request=None):
        """Get required permissions and return them"""
        
    def check_permissions(self, request):
        """Returns whether user has permissions"""
        
    def dispatch(self, request, *args, **kwargs):
        """Check user has required permission"""

Usage example:

from django.views.generic import UpdateView
from braces.views import PermissionRequiredMixin

class EditPostView(PermissionRequiredMixin, UpdateView):
    model = Post
    permission_required = 'blog.change_post'
    object_level_permissions = True  # Check permission on specific object
    raise_exception = True  # Return 403 instead of redirect

Multiple Permission Requirements

Complex permission checking with AND/OR logic for multiple permissions.

class MultiplePermissionsRequiredMixin(PermissionRequiredMixin):
    """Allows specifying multiple permissions with 'all' and 'any' logic"""
    permissions = None  # Dict with 'all' and/or 'any' keys
    
    def get_permission_required(self, request=None):
        """Get which permission is required"""
        
    def check_permissions(self, request):
        """Get the permissions, both all and any"""

Usage example:

from django.views.generic import CreateView
from braces.views import MultiplePermissionsRequiredMixin

class CreatePostView(MultiplePermissionsRequiredMixin, CreateView):
    model = Post
    permissions = {
        'all': ('blog.add_post', 'blog.change_post'),  # Must have ALL of these
        'any': ('blog.publish_post', 'user.is_editor')  # Must have ANY of these
    }

Group Membership

Require membership in specific Django groups.

class GroupRequiredMixin(AccessMixin):
    """Requires user membership in specific group(s)"""
    group_required = None  # String, list, or tuple of group names
    
    def get_group_required(self):
        """Get which group's membership is required"""
        
    def check_membership(self, groups):
        """Check user's membership in required groups"""
        
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler if user is group member"""

Usage example:

from django.views.generic import ListView
from braces.views import GroupRequiredMixin

class AdminListView(GroupRequiredMixin, ListView):
    model = MyModel
    group_required = ['admins', 'moderators']  # User must be in one of these groups

Custom User Tests

Custom validation logic for user access control.

class UserPassesTestMixin(AccessMixin):
    """User must pass custom test before accessing view"""
    
    def test_func(self, user):
        """The function to test the user with - must be implemented"""
        
    def get_test_func(self):
        """Get the test function"""
        
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler if user passes test"""

Usage example:

from django.views.generic import DetailView
from braces.views import UserPassesTestMixin

class ProfileView(UserPassesTestMixin, DetailView):
    model = Profile
    
    def test_func(self, user):
        profile = self.get_object()
        return user == profile.user or user.is_staff

Superuser and Staff Requirements

Quick access control for administrative users.

class SuperuserRequiredMixin(AccessMixin):
    """Require users to be superusers"""
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler if user is superuser"""

class StaffuserRequiredMixin(AccessMixin):
    """Require users to be marked as staff"""
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler if user is staff member"""

Usage example:

from django.views.generic import ListView
from braces.views import SuperuserRequiredMixin

class AdminOnlyView(SuperuserRequiredMixin, ListView):
    model = SensitiveModel
    raise_exception = True

Secure Connection Requirement

Enforce HTTPS connections with automatic redirect or error handling.

class SSLRequiredMixin:
    """Require requests to be made over secure connection"""
    raise_exception = False
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate handler if connection is secure"""

Usage example:

from django.views.generic import FormView
from braces.views import SSLRequiredMixin

class PaymentFormView(SSLRequiredMixin, FormView):
    template_name = 'payment.html'
    raise_exception = True  # Return 404 for non-HTTPS requests

Recent Login Requirement

Force re-authentication after a specified time period.

class RecentLoginRequiredMixin(LoginRequiredMixin):
    """Require user to have logged in within number of seconds"""
    max_last_login_delta = 1800  # Default 30 minutes
    
    def dispatch(self, request, *args, **kwargs):
        """Call appropriate method if user's login is recent"""

Usage example:

from django.views.generic import UpdateView
from braces.views import RecentLoginRequiredMixin

class SensitiveUpdateView(RecentLoginRequiredMixin, UpdateView):
    model = UserProfile
    max_last_login_delta = 900  # Require login within last 15 minutes

Common Usage Patterns

Combining Access Controls

Multiple access mixins can be combined for layered security:

from braces.views import LoginRequiredMixin, PermissionRequiredMixin, SSLRequiredMixin

class SecureAdminView(SSLRequiredMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView):
    model = SensitiveModel
    permission_required = 'myapp.change_sensitivemodel'
    raise_exception = True

Mixin Order

Access mixins should be placed leftmost in the inheritance chain (except when combined with CsrfExemptMixin, which should be leftmost).

Install with Tessl CLI

npx tessl i tessl/pypi-django-braces

docs

access-control.md

ajax-json.md

form-processing.md

http-utilities.md

index.md

query-optimization.md

tile.json