Django学习笔记一十九——补充内容:视图中的CBV和FBV (2020-05-15 15:05)

前面的总结忘记了很重要的一项:视图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对象。

CBV和FBV

 我们前面写的所有的视图都是基于函数的,就叫做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是没有哪个好哪个不好的,适合的就是最好的。

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

上面的方法是指定函数必须通过校验。

原文地址:https://www.cnblogs.com/yinsedeyinse/p/12907842.html