Django进阶之FBV和CBV

Django请求生命周期

Django的请求生命周期是指当用户在浏览器上输入url到用户看到网页的这个时间段内,Django后台所发生的事情。

  1. 当用户在浏览器中输入url时,浏览器会生成请求头和请求体发给服务端。
  2. url经过Django中的wsgi,再经过Django的中间件,最后到达路由映射表,在路由中一条一条进行匹配,一旦其中一条匹配成功就执行对应的视图函数,后面的路由就不再继续匹配了。
  3.  视图函数根据客户端的请求查询相应的数据,返回给Django,然后Django把客户端想要的数据做为一个字符串返回。
  4. 经过一系列的中间件,最后到达客户端。
  5.  客户端浏览器接收到返回的数据,经过渲染后显示给用户。

上面是FBV模式的请求过程。其实除了FBV之外Django还支持CBV模式。CBV模式的请求过程和FBV有些不同(下面会讲解二者的不同)。
当服务端使用CBV模式的时候,服务端通过路由映射匹配成功后会自动去执行对应类中的dispatch方法,然后会通过dispatch反射
的方式找到类中对应的方法并执行类中的方法,执行完毕之后,会把客户端想要的数据返回给dispatch方法,由dispatch方法把数据返回给客户端。

FVB

FBV(function base views)基于函数的视图, 就是在视图里使用函数处理请求。

urls.py:

urlpatterns = [
    url(r'^index/', views.index),
]

views.py:

def index(request):
    if request.method == 'GET':
        return HttpResponse('GET请求')
    elif request.method == 'POST':
        return HttpResponse('POST请求')

FBV模式需要自己判断请求方式,根据请求方式的不同执行不同的操作。

CBV

CBV(class base views)基于类的视图, 就是在视图里使用类处理请求。

urls.py:

urlpatterns = [   
    url(r'^student/', views.StudentView.as_view()),
]

views.py:

from django.views import View


class StudentView(View): 
    def get(self, request, *args, **kwargs):
        return HttpResponse('GET请求')

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

当服务端使用CBV模式的时候,服务端通过路由映射匹配成功后会自动去执行对应类中的dispatch方法,然后会通过dispatch反射的方式找到类中对应的方法并执行类中的方法,执行完毕之后,会把客户端想要的数据返回给dispatch方法,由dispatch方法把数据返回给客户端。

帮助理解CBV的执行过程:

class StudentView(View):
    # 调用父类的dispatch(默认),并做些自己需要的操作
    def dispatch(self, request, *args, **kwargs):
        if request.method == 'GET':  # 在指定的请求方法到来时先做的操作。
            print('GET 请求')
        print('before')  # 在所有的请求方法到来时先做的操作
        result = super(StudentView, self).dispatch(request, *args, **kwargs)
        print('after')
        return result

    # 拦截(证明最后的数据是由dispatch返回给客户端的)
    # def dispatch(self, request, *args, **kwargs):
    #     return HttpResponse('拦截')

    # 自定义dispatch
    # def dispatch(self, request, *args, **kwargs):
    #     func = getattr(self, request.method.lower())  # self = StudentView()
    #     return func(request, *args, **kwargs)

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

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

 

当有多个视图类都需要在dispatch方法中执行一些形同的操作是我们可以采用继承的方式:

class MyBaseView(object):
    def dispatch(self, request, *args, **kwargs):
        if request.method == 'GET':  # 在指定的请求方法到来时先做的操作。
            print('GET 请求')
        print('before')  # 在所有的请求方法到来时先做的操作
        result = super(MyBaseView, self).dispatch(request, *args, **kwargs)
        print('after')
        return result


class StudentView(MyBaseView, View):
    def get(self, request, *args, **kwargs):
        return HttpResponse('GET请求')

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


class TeacherView(MyBaseView, View):
    def get(self, request, *args, **kwargs):
        return HttpResponse('TeacherView中的GET请求')

    def post(self, request, *args, **kwargs):
        return HttpResponse('TeacherView中的POST请求')
View Code

在上面的代码中我们需要弄明白的一点是super()的作用,看下面这行代码

result = super().dispatch(request, *args, **kwargs)

我们平常可能认为上面这行代码的super()是执行MyBaseView类的父类中的dispatch方法,但是我们会发现MyBaseView的父类继承的是object类,但是object类中没有dispatch方法啊,这是怎么回事呢。

其实super()并不是简单的执行父类中的方法。super(MyBaseView, self) 获得的是 MyBaseView类 在 self这个对象的 MRO 列表中的下一个类。关于super()的详细介绍转到你不知道的super

 

posted @ 2018-03-25 18:12  流星之泪  阅读(281)  评论(0)    收藏  举报