如何在cbv的情况下添加装饰器
前言
首先,什么是装饰器我们都知道,有什么作用,也很清楚,比如说你要在淘宝上查看你购物车的详情,或者已经购买过的历史订单,那就需要你先登录淘宝账户,那这时候为了方便,就需要一个通用的登录的认证装饰器,所以接下来就开始吧!
先用cbv写一个简单的用户登录和查看订单接口
class Login(View): # 用户登录 def get(self, request, *args, **kwargs): return render(request, 'login.html') def post(self, request, *args, **kwargs): name = request.POST.get('name') pwd = request.POST.get('pwd') ret = models.User.objects.filter(name=name, pwd=pwd).first() # 登录成功记录session if ret: request.session['id'] = ret.pk request.session['name'] = ret.name return HttpResponse('登录成功') else: return HttpResponse('用户名或密码错误') class Order(View): # 订单详情 def get(self, request, *args, **kwargs): return HttpResponse('订单详情。。。') def post(self, request, *args, **kwargs): return HttpResponse('ok')
再写一个简单的前端登录界面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login</title> </head> <body> <form action="" method="post"> <p>name:<input type="text" name="name"></p> <p>pwd:<input type="password" name="pwd"></p> <input type="submit" value="登录"> </form> </body> </html>
OK!现在可以编写一个简单的无参装饰器
def login_auth(func): # 登录认证装饰器 def inner(request, *args, **kwargs): url = request.get_full_path() if request.session.get('id'): res = func(request, *args, **kwargs) else: return redirect('/login/?next={}'.format(url)) return res return inner
给Order类添加装饰器
注意:不能直接将装饰器加在函数上面,不然会报错('Order' object has no attribute 'get_full_path'),此时装饰器inner函数中的request参数是Order实例化后的self,self去调get_full_path()肯定出错,那如果你说我给request加个self不就OK了(self.request),是的,但是这样做你这个装饰器就不能通用了
# 错误的使用方法 class Order(View): @login_auth def get(self, request, *args, **kwargs): return HttpResponse('订单详情。。。') def post(self, request, *args, **kwargs): return HttpResponse('ok')
加给函数不行,那加给类就更不行了,程序直接就会跑不起来的
那这个时候就需要导入Django的method_decorator方法,此时为了实现登录后跳转的功能,就需要对Login类的post方法做个简单的修改
添加装饰器的第一种方法:
from django.shortcuts import render, redirect, HttpResponse from django.views import View from app01 import models from django.utils.decorators import method_decorator class Login(View): def get(self, request, *args, **kwargs): return render(request, 'login.html') def post(self, request, *args, **kwargs): name = request.POST.get('name') pwd = request.POST.get('pwd') ret = models.User.objects.filter(name=name, pwd=pwd).first() # 登录成功记录session if ret: url = request.GET.get('next') request.session['id'] = ret.pk request.session['name'] = ret.name # return HttpResponse('登录成功') return redirect(url) else: return HttpResponse('用户名或密码错误') # 方法一:加在类上面,将装饰器当参数传给method_decorator,然后指定要装饰的方法名 @method_decorator(login_auth, name='get') @method_decorator(login_auth, name='post') class Order(View): def get(self, request, *args, **kwargs): return HttpResponse('订单详情。。。') def post(self, request, *args, **kwargs): return HttpResponse('ok')
添加装饰器的第二种方法:
from django.shortcuts import render, redirect, HttpResponse from django.views import View from app01 import models from django.utils.decorators import method_decorator class Login(View): def get(self, request, *args, **kwargs): return render(request, 'login.html') def post(self, request, *args, **kwargs): name = request.POST.get('name') pwd = request.POST.get('pwd') ret = models.User.objects.filter(name=name, pwd=pwd).first() # 登录成功记录session if ret: url = request.GET.get('next') request.session['id'] = ret.pk request.session['name'] = ret.name # return HttpResponse('登录成功') return redirect(url) else: return HttpResponse('用户名或密码错误') class Order(View): # 方法二,直接在方法上加装饰器,将装饰器当做参数传给method_decorator @method_decorator(login_auth) def get(self, request, *args, **kwargs): return HttpResponse('订单详情。。。') @method_decorator(login_auth) def post(self, request, *args, **kwargs): return HttpResponse('ok')
最后别忘了配置理由
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.Login.as_view()), url(r'^order/', views.Order.as_view()), ]
OK!这就简单实现了在cbv的情况下,给函数(类)加装饰器
本文来自博客园,仅供参考学习,如有不当之处还望不吝赐教,不胜感激!转载请注明原文链接:https://www.cnblogs.com/rong-z/articles/10297039.html
作者:cnblogs用户