[英]Django - How to use decorator in class-based view methods?
I am developing a site with django 1.8. 我正在用django 1.8开发一个网站。 This is an example of one of the Views:
这是其中一个视图的示例:
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('/')
The question is, can I have different decorators according to the type of request that is made to a controller (view)? 问题是,根据对控制器(视图)的请求类型,我可以有不同的装饰器吗?
Since Django 1.9, according to the doc , it is possible to apply decorator in the next way: 从Django 1.9开始, 根据文档 ,可以在下一个方式应用装饰器:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
@method_decorator(login_required, name='dispatch')
class YourClassBasedView(TemplateView):
...
where name
is the name of the method to be decorated. 其中
name
是要装饰的方法的名称。
or in case of few decorators: 或者在少数装饰者的情况下:
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):
...
You need to apply the decorator to the dispatch method of the class based view. 您需要将装饰器应用于基于类的视图的dispatch方法。 This can be done as follows:
这可以按如下方式完成:
class ProfileView(View):
@youdecorator
def dispatch(self,request,*args,**kwargs):
return super(ProfileView,self).dispatch(request,*args,**kwargs)
//Rest of your code.
There is a very simple solution to achieve what you want, and it doesn't implies decorating dispatch
method. 有一个非常简单的解决方案来实现您想要的,它并不意味着装饰
dispatch
方法。 You must use the method_decorator
over your methods (get/post) and pass the decorator call (not the decorator itself) as a parameter. 您必须对方法(get / post)使用
method_decorator
并将装饰器调用 (不是装饰器本身)作为参数传递。
In your case it would be: 在你的情况下,它将是:
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):
...
Note the parethesis in the login_required
decorator. 请注意
login_required
装饰器中的parethesis。
You can pass any function-oriented decorator, even a custom one. 您可以传递任何面向函数的装饰器,甚至是自定义装饰器。 For instance:
例如:
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
And then, again: 然后,再次:
class YourView(View):
@method_decorator(white_list_check())
def get(self, request):
...
Some decorators like never_cache can be used in the urls.py in stead of the old way: in views.py 像never_cache这样的装饰器可以在urls.py中使用而不是旧的方式:在views.py中
eg the never_cache decorator: 例如,never_cache装饰器:
in the old style views.py: 在旧式的views.py中:
from django.views.decorators.cache import never_cache
@never_cache
def oldstyle_view(request):
# and so on
when using class based views, in urls.py: 在urls.py中使用基于类的视图时:
from django.views.decorators.cache import never_cache
urlpatterns = patterns('',
(r'someurl/^$', never_cache(SomeClassBasedView.as_view())),
)
Edit 1st aug 2015 编辑2015年8月1日
Note: this can be handy for those views where you do not have a complete view defined in views.py, otherwhise the decorator can be applied to the depatch method in the view as well. 注意:对于那些没有在views.py中定义完整视图的视图,这可以很方便,除此之外,装饰器也可以应用于视图中的depatch方法。
You can override dispatch
method and call different decorators based on type of request: 您可以覆盖
dispatch
方法并根据请求类型调用不同的装饰器:
from django.utils.decorators import method_decorator
class ProfileView(View):
...
def dispatch(self, *args, **kwargs):
dispatch_method = super(ProfileView, self).dispatch
if self.request.method == 'GET':
dispatch_method = method_decorator(my_get_decorator)(dispatch_method)
elif self.request.method == 'POST':
dispatch_method = method_decorator(my_post_decorator)(dispatch_method)
return dispatch_method(*args, **kwargs)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.