Django: Невозможно применить функциональный декоратор представления к представлению на основе классов
Я перехожу от обычных представлений, основанных на функциях, к представлениям, основанным на классах. Одной из вещей, которую я не смог перенести, были декораторы, которые я использовал. Декоратор, о котором идет речь, проверяет, действительны ли учетные данные текущего пользователя, а затем выполняет декорированную функцию:
def custom_auth(function):
@wraps(function)
def wrap(request, *args, **kwargs):
# Logic for validating if user has correct credentials
# Fetches the user that accessed the function
user_object = User.objects.get(username=request_username)
# Try to execute the decorated function. If it fails, redirect
# to previous page and show an error popup
try:
return function(request, user=user_object, *args, **kwargs)
except:
# Logic for displaying the popup
Раньше я мог просто украсить свою функцию, сделав
@custom_auth
def view(request, *args, **kwargs):
# View logic
Однако, когда я пытаюсь применить его к моему представлению на основе класса тем же способом, я получаю ошибку, говорящую __init__() takes 1 positional argument but 2 were given: user='username', view='cbvview'
@custom_auth
class CBV(View):
def get(self, request, *args, **kwargs):
# Get request logic
Я знаю, что это не тот способ, которым вы должны применять декоратор, поэтому я пробовал использовать различные подходы. Либо добавить декоратор к urls.py
, либо добавить @method_decorator(custom_auth, name="dispatch")
, либо просто переопределить метод диспетчеризации, но ни один из них не работает. Все они дают мне одну и ту же ошибку.
В чем может быть проблема? Может быть, мне следует использовать пользовательский миксин?
from django.utils.decorators import method_decorator
class CBV(View):
@method_decorator(custom_auth)
def get(self, request, *args, **kwargs):
# Get request logic
из документации django https://docs.djangoproject.com/en/4.1/topics/class-based-views/intro/
@method_decorator(login_required, name='dispatch')
class ProtectedView(TemplateView):
template_name = 'secret.html'
и нет необходимости добавлять пользователя к вызову функции в декораторе. Он уже есть в запросе
Используйте @method_decorator
следующим образом:
from django.utils.decorators import method_decorator
@method_decorator(custom_auth,name="dispatch")
class CBV(View):
def get(self, request, *args, **kwargs):
...
Редактирование:
Попробуйте сделать свой собственный mixin как класс и наследовать его для использования в CBV
классе так:
class CustomAuthMixin:
def dispatch(self, request, *args, **kwargs):
# Logic for validating if user has correct credentials
# Fetches the user that accessed the function
user_instance = User.objects.get(username=request_username)
# Try to execute the decorated function. If it fails, redirect
# to previous page and show an error popup
try:
return super().dispatch(request, user=user_instance, *args, **kwargs)
except:
# Logic for displaying the popup
class CBV(CustomAuthMixin, View):
def get(self, request, *args, **kwargs):
# Get request logic