如何在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用户
浙公网安备 33010602011771号