from functools import wraps from django.utils.decorators import classonlymethod from rest_framework.viewsets import ViewSetMixin try: from django_scopes import scope except ImportError: from xenua.decorators import no_op as scope try: from rest_framework import APIView except ImportError: APIView = None class ScopedViewMixin: def dispatch(self, request, *args, **kwargs): for method_name in self.http_method_names: if (method := getattr(self, method_name, None)) is not None: wrapped_method = wraps(method)(self.apply_scopes(method, method_name)) setattr(self, method_name, wrapped_method) return super().dispatch(request, *args, **kwargs) def apply_scopes(self, to: callable, http_method): def wrapper(request, *args, **kwargs): with scope(**self.get_scopes(request, *args, **kwargs)): return to(request, *args, **kwargs) return wrapper def get_scopes(self, request, *args, **kwargs): return {} class UserScopedViewMixin(ScopedViewMixin): user_scope_name = 'user' def get_scopes(self, r, *args, **kwargs): return {self.user_scope_name: r.user}