django中的CBV

Posted louyifei0824

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django中的CBV相关的知识,希望对你有一定的参考价值。

CBV介绍

我们在写一个django项目时,通常使用的都是FBV(function base views)

而CBV(class base views)也有它自己的应用场景,比如在写一个按照rest规范写接口时,CBV的适用性就比FBV更强

先来看看CBV在django中的写法,与FBV有什么不同的地方

技术分享图片
url(r^students/, views.StudentsView.as_view())
路由
技术分享图片
from django.views import View

class StudentsView(View):

    def get(self,request,*args,**kwargs):
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)
视图

技术分享图片

首先,在views中定义的类是要继承django中的View类的,而StudentsView中并未定义as_view()这个方法,所以它会去执行View中的as_view方法

而as_view方法的返回值就是一个函数,这个函数是在as_view中的内部定义的

那么在我们访问url的时候,django会去调用这个view函数,view函数又去调用了self.dispatch方法,并返回了这个方法的返回值

所以查看一下dispatch这个方法

技术分享图片

它就是对这个请求的method做了一个反射的操作,找到这个请求类型对应的方法然后去执行它,lower()的作用就是把method中的GET/POST等大写的方法名转化成小写的函数名,这样我们只需要在类中定义好小写的函数名就可以完成调用了

原理:
url -> view方法 -> dispatch方法(反射执行其他:GET/POST/DELETE/PUT)

技术分享图片
流程:
class StudentsView(View):
    def dispatch(self, request, *args, **kwargs):
        print(before)
        ret = super(StudentsView,self).dispatch(request, *args, **kwargs)
        print(after)
        return ret

    def get(self,request,*args,**kwargs):
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)

继承(多个类共用的功能,为了避免重复编写):
from django.views import View


class MyBaseView(object):
    def dispatch(self, request, *args, **kwargs):
        print(before)
        ret = super(MyBaseView,self).dispatch(request, *args, **kwargs)
        print(after)
        return ret

class StudentsView(MyBaseView,View): # 继承时要先继承我们自己定义的类,这样才有效,如果先继承View那么就会先去执行原码中的dispatch方法了

    def get(self,request,*args,**kwargs):
        print(get方法)
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)

class TeachersView(MyBaseView,View):

    def get(self,request,*args,**kwargs):
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)
流程

CBV中关于csrf一些需要注意的点

首先要知道csrf是如何实现的

django中的csrf是通过中间件中的process_view()方法来实现的

实现的过程分为两步:

第一步:检查视图是否被@csrf_exempt装饰器装饰

第二步:去请求体或cookie中获取token对应的值,并用算法与服务器发送给浏览器上的token值进行对比校验

技术分享图片
情况一:
MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    django.middleware.csrf.CsrfViewMiddleware, # 全站使用csrf认证
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
]


from django.views.decorators.csrf import csrf_exempt
@csrf_exempt # 该函数无需认证
def users(request):
    user_list = [alex,oldboy]
    return HttpResponse(json.dumps((user_list)))
情况一
技术分享图片
情况二:
MIDDLEWARE = [
    django.middleware.security.SecurityMiddleware,
    django.contrib.sessions.middleware.SessionMiddleware,
    django.middleware.common.CommonMiddleware,
    #‘django.middleware.csrf.CsrfViewMiddleware‘, # 全站不使用csrf认证
    django.contrib.auth.middleware.AuthenticationMiddleware,
    django.contrib.messages.middleware.MessageMiddleware,
    django.middleware.clickjacking.XFrameOptionsMiddleware,
]


from django.views.decorators.csrf import csrf_exempt
@csrf_protect # 该函数需认证
def users(request):
    user_list = [alex,oldboy]
    return HttpResponse(json.dumps((user_list)))
情况二

CBV小知识

csrf时需要使用
- @method_decorator(csrf_exempt)
- 在dispatch方法中(单独方法无效)

在cbv中使用csrf的方式也有两种

技术分享图片
方式一:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator
class StudentsView(View):
    
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(StudentsView,self).dispatch(request, *args, **kwargs)

    def get(self,request,*args,**kwargs):
        print(get方法)
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)
方式一
技术分享图片
方式二:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.utils.decorators import method_decorator

@method_decorator(csrf_exempt,name=dispatch)
class StudentsView(View):

    def get(self,request,*args,**kwargs):
        print(get方法)
        return HttpResponse(GET)

    def post(self, request, *args, **kwargs):
        return HttpResponse(POST)

    def put(self, request, *args, **kwargs):
        return HttpResponse(PUT)

    def delete(self, request, *args, **kwargs):
        return HttpResponse(DELETE)
方式二

 

以上是关于django中的CBV的主要内容,如果未能解决你的问题,请参考以下文章

django中的FBV和CBV

django中的CBV

Django中CBV和Restful API中的APIView源码分析

Django中的CBV和FBV

django中的FBV和CBV

Django:两个模型中的一个 url 搜索(cbv)