DRF进阶
2019-01-22 本文已影响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寻找视图函数
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