前面的总结忘记了很重要的一项:视图Views,还有视图的两种模式:CBV和FBV
视图就是一个视图函数(类),从Web接受请求然后给Web返回一个响应。响应可以是一个网页的HTML内容(HttpResponse),也可以是个重定向(redirect),也可以是个404错误,或者一个XML文档、一张图片。
视图是必须有返回值的,不管他是什么逻辑,最后都要返回一个response,只需要把他放在当前的目录下面,就没有什么别的特别需求了。但是有个约定俗成的习惯,就是把代码放在项目或应用程序中(app)的views.py文件中。
我们看一下下面的代码
from django.shortcuts import HttpResponse def test(request): print('in test') return HttpResponse('test123')
上面就是一个最简单的视图,有请求(输入的request),有返回(HttpResponse)
首先,我们从Django中导入了HttpResponse模块
接着,我们随便做了一个功能。功能的逻辑直接忽略。然后返回一个HttpResponse对象。
我们前面写的所有的视图都是基于函数的,就叫做FBV(function base views),除此以外,还可以把视图携程基于类的,就是CBV(Class base views),我们就用一个最简单的案例来比较一下CBV和FBV的区别
一个简单的视图
就是一个注册的页面,先看看FBV的效果
def login(request): if request.method == 'POST': name = request.POST.get('user') pwd = request.POST.get('pwd') if name == 'aaa' and pwd =='bbb': rep = HttpResponse('登录成功') return rep else: return redirect('/session_test/login') else: return render(request,'login.html')
然后再看看CBV是怎么写的
from django.views import View class Login(View): #method为get def get(self,request): return render(request,'login.html') #method为post def post(self,request): name = request.POST.get('user') pwd = request.POST.get('pwd') if name == 'aaa' and pwd =='bbb': rep = HttpResponse('登录成功') return rep else: return redirect('/session_test/login')
但是两个方法在路由中注册的时候是有区别的
url('^session_test/login',v2.login), #FBV的注册方法 url('^session_test/login',v2.Login.as_view()), #CBV的注册方法
FBV和CBV是没有哪个好哪个不好的,适合的就是最好的。
在FBV中,由于我们用到的装饰器都是函数装饰器,用来装饰函数的,但是在CBV中就会出问题了,看一下下面的案例,还是前面讲过的登录校验
def check_login(func): @wraps(func) def inner(request,*args,**kwargs): ret = request.session.get('is_log') if ret == 1: return func(request,*args,**kwargs) else: return redirect('/session_test/login/') return inner class Home(View): @check_login def get(self,request): return render(request,'home.html')
我们对一个页面在请求的时候先进行登录校验,如果没有登录就重新登录,否则直接进入主页面。但是这样运行完了会出现bug
原因就是我们在对装饰器传参数的时候,第一个参数是request,但是在类里的函数中,第一个参数就是self,当然会报错,所以这个装饰器就是函数装饰器,我们需要在使用的时候把他指定成类装饰器:
from django.utils.decorators import method_decorator class Home(View): @method_decorator(check_login) def get(self,request): return render(request,'home.html')
这样就可以了!
加给类的装饰器
刚才的装饰器是直接加给类里面的方法的,我们还可以直接加到类上
@method_decorator(check_login,name='get') class Home(View): def get(self,request): return render(request,'home.html')
但是要注意的是加载类的前面的时候必须用关键字name指定装饰器是给哪个方法用的。
我们前面的所有案例中,对于跨站伪装请求的处理有两种方法:
1.在settings.py文件中直接注释掉csrf的中间件
2.在form中通过{token_csrf}获取到csrf的标签
其实还可以通过装饰器来处理
排除校验
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_exempt def login(requst): pass
上面的装饰器可以使被装饰的函数排除校验(即便是中间件指定了校验)
指定校验
from django.views.decorators.csrf import csrf_exempt,csrf_protect @csrf_protect def login(requst): pass
上面的方法是指定函数必须通过校验。