python Django:无法将函数视图装饰器应用于基于类的视图

vecaoik1  于 2023-02-07  发布在  Python
关注(0)|答案(3)|浏览(156)

我正在从常规的基于函数的视图迁移到基于类的视图。我不能迁移的东西之一是我使用的装饰器。所讨论的装饰器检查当前用户的凭证是否有效,然后执行装饰的函数:

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"),或者简单地覆盖调度方法,但是它们都不起作用,都给予我同样的错误。
可能是什么问题?也许我应该使用一个自定义的mixin代替?

noj0wjuj

noj0wjuj1#

来自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'

并且不需要在装饰器中将用户添加到函数调用中,它已经在请求中了

gab6jxml

gab6jxml2#

按如下方式使用@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
mklgxw1f

mklgxw1f3#

from django.utils.decorators import method_decorator
class CBV(View):
    
  @method_decorator(custom_auth)
  def get(self, request, *args, **kwargs):
      # Get request logic

相关问题