Django-如何在基于类的视图方法中使用decorator?

2024-03-29 08:19:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在开发一个网站与django 1.8。以下是其中一个视图的示例:

class ProfileView(View):
    template_name = 'index.html'

    # Return profile of any role (client/employee/admin)
    # Login required
    def get(self, request, *args, **kwargs):
        try:
            profile = Profile.objects.get(user=request.user)
            agency = None

            if request.user.is_employee():
                employee = EmployeeProfile.objects.get(profile=profile)
                agency = employee.agency

            if request.user.is_manager():
                agency = Agency.objects.get(manager=request.user)

        except (Profile.DoesNotExist, EmployeeProfile.DoesNotExist, Agency.DoesNotExist) as e:
            return HttpResponseRedirect('/404')

        return render(request, self.template_name, {"profile": profile, "agency": agency})

    # Client sign up
    # No decorator is needed
    def post(self, request):
        sign_up = SignUpForm(request.POST, request.FILES)

        response = json.loads(utils.create_user(sign_up,request.POST['avatar']))
        if response['profile'] is None:
            return JsonResponse({"code": 400, "response": response['message']})
        profile = serializers.deserialize("json", response['profile']).next().object

        group = Group.objects.get(name='clients')
        profile.user.groups.add(group)

        return HttpResponseRedirect('/')

问题是,我可以根据对控制器(视图)的请求类型使用不同的装饰器吗?


Tags: nameselfgetreturnifobjectsisresponse
3条回答

有一个非常简单的解决方案来实现您想要的,它并不意味着装饰dispatch方法。必须在方法(get/post)上使用method_decorator,并将decorator调用(而不是decorator本身)作为参数传递。

在你的情况下是:

from django.utils.decorators import method_decorator

class ProfileView(View):
template_name = 'index.html'

    # Return profile of any role (client/employee/admin)
    @method_decorator(login_required())
    def get(self, request, *args, **kwargs):
        ...

    # Client sign up
    # No decorator is needed
    def post(self, request):
        ...

注意login_requireddecorator中的parethesis。

您可以传递任何面向函数的decorator,甚至是自定义的decorator。例如:

def white_list_check():
    def decorator(func):
        def wrapper(request, *args, **kwargs):
            ip = request.META.get('REMOTE_ADDR', '0.0.0.0')
            if ip in WHITE_LIST:
                return func(request, *args, **kwargs)
            else:
                return HttpResponseForbidden()
        return wrapper
    return decorator

然后,再一次:

class YourView(View):

    @method_decorator(white_list_check())
    def get(self, request):
        ...

因为Django 1.9,according to the doc,所以可以用下面的方法应用decorator:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator

@method_decorator(login_required, name='dispatch')
class YourClassBasedView(TemplateView):
    ...

其中name是要修饰的方法的名称。

或者在很少的装修师的情况下:

from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import never_cache
from django.utils.decorators import method_decorator

decorators = [never_cache, login_required]

@method_decorator(decorators, name='dispatch')
class YourClassBasedView(TemplateView):
    ...

您需要将decorator应用于基于类的视图的分派方法。具体操作如下:

class ProfileView(View):

    @youdecorator
    def dispatch(self,request,*args,**kwargs):
        return super(ProfileView,self).dispatch(request,*args,**kwargs)
    //Rest of your code.

相关问题 更多 >