DRF进阶

作者: 瘦不下去了 | 来源:发表于2019-01-22 00:06 被阅读0次

    一、Django的FBV和CBV

    FBV:Function-base views基于函数的视图
    CBV:Class-base views基于类的视图

    from django.http import JsonResponse
    
    #FBV function base view
    def func_view(request):
        if request.method == 'GET':
            d = {
                'msg':'请求成功,GET',
                'status_code':1000
            }
            return JsonResponse(d)
        if request.method == 'POST':
            d = {
                'msg':'请求成功,POST',
                'status_code':1000
            }
            return JsonResponse(d)
    路由:
    from django.urls import path
    #from django.conf.urls import url
    from mypro import views
    urlpatterns = [
        ...
        #url(r'^func_view/$',views.func_view),
        path('func_view/',views.func_view),
        ...
    ]
    
    from django.views import View
    
    #CBV:Class-base views
    class MyClassView(View):
        def dispatch(self, request, *args, **kwargs):
            #hasteer 查看用户传来的request.method是否存在
            if hasattr(self,request.method.lower()):
                #获取对象的request.method所对应的属性和方法
                func = getattr(self,request.method.lower())
                return func(request,*args,**kwargs)
    
        def get(self,request,*args,**kwargs):
            return JsonResponse({'msg':'GET请求成功'})
        def post(self,request,*args,**kwargs):
            return JsonResponse({'msg':'POST请求成功'})
    路由:
    from django.urls import path
    #from django.conf.urls import url
    from mypro import views
    urlpatterns = [
        ...
        #url(r'MyClassView/$',views.MyClassView.as_view())
        path('MyClassView/',views.MyClassView.as_view())
    ]
    

    二、列表生成式

    class Person(object):
        pass
    class Car(object):
        pass
    
    #列表生成式
    objs = [item() for item in [Person,Car]]
    详解为:
    obj_list = []
    for i in [Person,Car]:
        #在这里i后面跟了个小括号,就相当于实例化了一个对象
        obj = i()
        obj_list.append(obj)#这里obj_list里装的是一个对象
    

    三、面向对象

    class Request(object):
        def __init__(self,obj):
            self.obj = obj
    
        @property
        def user(self):
            return self.obj.authticate()
    
    class Auth(object):
        def __init__(self,name,age):
            self.name = name
            self.age = age
    
        def authticate(self):
            return self.name
    
    class APIView(object):
        def dispath(self):
            self.f2()
    
        def f2(self):
            a = Auth('lhd',22)
            b = Auth('lhn',22)
            req = Request(b)
            print(req.user)
    
    obj = APIView()
    obj.dispath()
    
    #lhn
    

    四、反射

    通过字符串映射object对象的方法或者属性

    方法 说明
    hasattr(obj,name_str) 判断object是否有name_str这个方法或者属性
    getattr(obj,name_str) 获取object对象中与name_str同名的方法或者属性
    setattr(obj,name_str,value) 为object对象设置一个以name_str命名的value属性或者方法
    delattr(obj,name_str) 删除object对象中的name_str方法或者属性
    class Person(object):
        def __init__(self,name):
            self.name = name
    
        def eat(self):
            print('{}正在吃'.format(self.name))
    
        def run(self):
            print('{}正在跑'.format(self.name))
    #实例化一个对象
    zs = Person('张三')
    #让用户输入一个指令来调用什么属性或者方法
    mystr = input('请输入:')
    #判断是否存在
    if hasattr(zs,mystr):
        #存在就用func接收
        func = getattr(zs,mystr)
        #通过类型判断是属性还是方法,
        #因为getattr必须是同名方法或者属性,前面实例化的时候名字是字符串
        #所以以此来区分是属性还是方法,
        if type(func) == str:
            print(func)
        else:
            func()
    else:
        print('操作有误')
    
    setattr
    
    def sing(self):
        print('{}正在唱'.format(self.name))
    
    class Person(object):
        def __init__(self,name):
            self.name = name
    
        def eat(self):
            print('{}正在吃'.format(self.name))
    
        def run(self):
            print('{}正在跑'.format(self.name))
    #实例化一个对象
    zs = Person('张三')
    #让用户输入一个指令来调用什么属性或者方法
    mystr = input('请输入:')
    #判断是否存在
    if hasattr(zs,mystr):
        #存在就用func接收
        func = getattr(zs,mystr)
        #通过类型判断是属性还是方法,
        #因为getattr必须是同名方法或者属性,前面实例化的时候名字是字符串
        #所以以此来区分是属性还是方法,
        if type(func) == str:
            print(func)
        else:
            func()
    else:
        setattr(zs,mystr,sing)
        func = getattr(zs,mystr)
        func(zs)
    
    delattr
    
    class Person(object):
        def __init__(self,name):
            self.name = name
    
        def eat(self):
            print('{}正在吃'.format(self.name))
    
        def run(self):
            print('{}正在跑'.format(self.name))
    #实例化一个对象
    zs = Person('张三')
    #让用户输入一个指令来调用什么属性或者方法
    mystr = input('请输入:')
    
    #以name属性为例
    print('删除前:{}'.format(zs.name))
    try:
        if hasattr(zs,mystr):
            delattr(zs,mystr)
    except AttributeError:
        print('删除{}成功:'.format(mystr))
    print('删除后:{}'.format(zs.name))
    

    实际应用

    import requests
    
    class Http(object):
        def get(self,url):
            req = requests.get(url)
            response = req.text
            return response
        def post(self,url):
            req = requests.get(url)
            response = req.text
            return response
    
    #使用反射前
    url = 'https://www.baidu.com/'
    mystr = input('请输入:')
    #实例化一个对象
    h = Http()
    result = ''
    #根据用户的输入判断
    #upper():将所有小写字母转换成大写
    if mystr.upper() == 'GET':
        result = h.get(url)
    elif mystr.upper() == 'POST':
        result = h.get(url)
    else:
        print('请求有误')
    
    
    #使用反射后
    url = 'https://www.baidu.com/'
    mystr = input('请输入:')
    h = Http()
    if hasattr(h,mystr):
        func = getattr(h,mystr)
        res = func(url)
        print(res.text)
    else:
        print('请求方式有误')
    

    五、CBV基本的使用和源码执行流程

    from django.http import JsonResponse
    from django.views import View
    
    #CBV写法
    def func_view(request):
        if request.method == 'GET':
            return JsonResponse({'method':'GET请求','status_code':1000})
        elif request.method == 'POST':
            return JsonResponse({'method':'POST请求','status_code':1000})
        elif request.method == 'DELETE':
            return JsonResponse({'method':'DELETE请求','status_code':1000})
        else:
            return JsonResponse({'method':'不支持的请求方式','status_code':1001})
    #CBV写法
    class MyClassView(View):
        def get(self,request,*args,**kwargs):
            return JsonResponse({'method':'GET请求','status_code':1000})
        def post(self,request,*args,**kwargs):
            return JsonResponse({'method':'POST请求','status_code':1000})
        def delete(self,request,*args,**kwargs):
            return JsonResponse({'method':'DELETE请求','status_code':1001}
    

    原理

    FBV可以直接通过路由,调用到相应的视图

    CBV执行流程则如下
    1.通过url寻找视图函数

    image.png
    2.在我们的MyClassView里没有as_view(),所以我们去父类找
    image.png
    3.找到父类的as_view()方法
    image.png
    4.在as_view中也返回一个view
    image.png
    5.分析as_view()中的源码,调用了dispatch()方法
    image.png
    6.在分析dispatch()方法前,先看,当请求进来,通过url先执行了as_view()函数,本质还是在执行内部的view()函数,而view()函数内部则调用了diapatch方法()
    image.png
    7.不管什么请求进来,都要执行dispatch方法
    image.png
    8.由于我们的MyClassView里没有dispatch()方法,所以会调用父类的dispatch()方法,如果我们有,就调用我们自己的
    image.png
    image.png
    9.自己尝试写dispatch
    image.png
    image.png
    image.png
    • dispatch都做了什么?
      image.png

    结论:CBV基于反射实现根据不同请求方式,执行不同方法
    原理:路由url-->view函数-->dispatch方法(根据反射来执行:GET,POST,PUT,DELETE等等)

    拓展1

    • 调用父类方法

      image.png
    • 源码执行流程

      image.png
      image.png

    拓展2

    image.png
    做一些更改后:
    image.png
    说明:也就是说在执行中间的dispatch方法的时候,直接在这个父类的dispatch方法里面调用了下一个父类View的dispatch方法,
    image.png
    image.png

    拓展3

    CSRF(Cross-site request forgery)跨站请求伪造,由于目标站无token/referer限制,导致攻击者可以用户的身份完成操作达到各种目的

    • FBV:去请求体或者Cookie中获取token
      image.png
      说明:csrf_protect是对某个视图函数启用csrf
    • CBV


      image.png

    相关文章

      网友评论

          本文标题:DRF进阶

          本文链接:https://www.haomeiwen.com/subject/yydhjqtx.html