DRF进阶

一、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寻找视图函数

12865014-1ffa9a31558ecec9.png
image.png

2.在我们的MyClassView里没有as_view(),所以我们去父类找
12865014-ddfa65a8236ee4dd.png
image.png

3.找到父类的as_view()方法
12865014-2ad542a9b40a6a1e.png
image.png

4.在as_view中也返回一个view
12865014-1747563666223216.png
image.png

5.分析as_view()中的源码,调用了dispatch()方法
12865014-1e427845dbd0db9b.png
image.png

6.在分析dispatch()方法前,先看,当请求进来,通过url先执行了as_view()函数,本质还是在执行内部的view()函数,而view()函数内部则调用了diapatch方法()
12865014-01afad0c839fd343.png
image.png

7.不管什么请求进来,都要执行dispatch方法
12865014-50458ac4d23fa373.png
image.png

8.由于我们的MyClassView里没有dispatch()方法,所以会调用父类的dispatch()方法,如果我们有,就调用我们自己的
12865014-a72d59e896e94b77.png
image.png

12865014-770228c2a09a1dda.png
image.png

9.自己尝试写dispatch
12865014-079ef71b83f88088.png
image.png

12865014-61dd3f46015cd59e.png
image.png

12865014-c406d26eff277732.png
image.png

  • dispatch都做了什么?
    12865014-030970383b4b0464.png
    image.png

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

拓展1

  • 调用父类方法

    12865014-4f4b73f4f19afe36.png
    image.png

  • 源码执行流程

    12865014-b097662d35e2029b.png
    image.png

    12865014-ccd8af5fbcf500a0.png
    image.png

拓展2

12865014-e2e7edafe815d70f.png
image.png

做一些更改后:
12865014-c6cb4d06032ae614.png
image.png

说明:也就是说在执行中间的dispatch方法的时候,直接在这个父类的dispatch方法里面调用了下一个父类View的dispatch方法,
12865014-79a96ea5cb170165.png
image.png

12865014-b4f58d30df9ed818.png
image.png

拓展3

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

  • FBV:去请求体或者Cookie中获取token
    12865014-de8e7deda7c47349.png
    image.png

    说明:csrf_protect是对某个视图函数启用csrf
  • CBV


    12865014-239cba01c6768e22.png
    image.png

猜你喜欢

转载自blog.csdn.net/weixin_34138521/article/details/87234916
DRF