DRF request对象、 Serializer
-
CBV的源码分析
-
drf之APIView的执行流程分析
-
drf的Request对象分析
-
序列化类Serializer的使用
CBV的源码分析
#注意django2.x 路由层不一样了 不用url 用path re_path等于django1.x的url(不推荐使用)
from django.urls import path
#views.IndexView.as_view() 等于 继承的View里面的asview里面的view的内存地址
path('index/',views.IndexView.as_view()) #路由方法里第二个参数就是内存地址
大概流程 入口 在urls 里面调用量.as_view() 属于调用 这个方法类里没有 去父类找 ,发现as_view方法return一个view 的内存地址 所以 urls里面第二个参数就是这个view的内存地址 然后看这个view 里面 生成了一个self=(**initkwargs) 所以 self 是对象 是 传进来的类的对象 然后发现view return了一个self.dispatch, 先去对象找 再去生成这个对象的类找 最后父类找 在父类找到了,这个dispatch方法里面先把请求方法转小写 并判断是不是在一个变量里 这个变量里存放了 get post put patch dlete 等等 如果在 则会利用反射得到一个内存地址 ,判断self 有没有这个请求的方法 并赋值 没有则调用一个报错方法 最后return 这个内存地址(request, *args, **kwargs) 调用
主要核心为dispatch
def dispatch(self, request, *args, **kwargs):
#判断请求方法转小写是不是在那八个方法里
if request.method.lower() in self.http_method_names:
#通过反射得到一个内存地址
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
# handler = getattr(self, 'get', self.http_method_not_allowed) # handler就是函数内存地址
else:
handler = self.http_method_not_allowed
# get, post, put ...
return handler(request, *args, **kwargs) # get(request, *args, **kwargs), post()
drf之APIView的执行流程分析
#注册 注册 注册 因为rest_framwork是应用 用Response 要记得注册不然他没有页面 其实是返回来Json数据
# 数据库迁移:
makemigrations app01 # 后面可以加应用名,代表只迁移这个应用下的数据
# 如果不加应用名,代表迁移所有应用的数据
#只要导入了rest_framework里面的东西 都要继承APIView ,APIView也继承了View 所以 CBV必须继承View
#推导过程 执行了ApiView里面的as_view
@classmethod
def as_view(cls, **initkwargs):
# View类的as_view()
view = super().as_view(**initkwargs) #view:是View里面的as_view里面的view的函数内存地址
return csrf_exempt(view) # 去掉了csrf的验证, 跟之前的加在视图函数上一毛一样 等同与view上面加个跳过csrf验证装饰器 return view的内存地址
#所有apiview都没有csrf认证
#get请求 如何运行
#走View里面的as_view里面的view函数 返回了self.dispatch 这个self 是 继承apiview的类产生的对象
#去的时候apiview的dispatch
def view(request, *args, **kwargs):
# self 就是IndexView类的对象
self = cls(**initkwargs) # IndexView()
return self.dispatch(request, *args, **kwargs)
# APIView的源码分析:
def dispatch(self, request, *args, **kwargs):
# 它封装了新的request, 后面的request还是Django的request
request = self.initialize_request(request, *args, **kwargs)
self.request = request # drf的request
try:
# 这个里面做了三大认证: 认证,权限,频率
self.initial(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
# 重点:
APIView做了三件事:
1. 把Django的request封装了新的request,drf的request
以后你在视图函数中,在使用request,就是新的request了。
2. 进行了三大认证:
self.perform_authentication(request) # 认证
self.check_permissions(request) # 权限
self.check_throttles(request) # 频率
3. 做了全局的异常处理
# 以后,只要继承了APIView, 在视图函数中使用的request都是新的request。
在执行视图函数之前,进行了三大认证。
drf的request对象分析
# request = self.initialize_request(request, *args, **kwargs) 老的request 执行了一个方法 变成了新的request
def initialize_request(self, request, *args, **kwargs):
return Request(
request,
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
class Request:
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
assert isinstance(request, HttpRequest), (
'The `request` argument must be an instance of '
'`django.http.HttpRequest`, not `{}.{}`.'
.format(request.__class__.__module__, request.__class__.__name__)
)
# 重点再下面一句话
self._request = request #老的request 值给了_request
# 为什么新的request和老的request使用起来一模一样?
是因为再Request类中重写了__getattr__方法
def __getattr__(self, attr):
try:
#通过反射 去老的request 取出属性或方法
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
# 新的request有什么特性?
多了一个data属性 request.data 感觉是个数据属性 其实是个方法
针对post请求的三种编码格式都可以从data属性中取到 urlencoded formdata json
序列化类Seaializer的使用
自定义一个serializer.py文件
#如果想使用序列化 需要继承Serializer
from rest_framework import serializers
class BookSerialzer(serializers.Serialzer)
title=serializers.CharField()
price=serializers.IntegerField()
#views
class BookView(APIView):
def get(self, request):
book_list = models.Book.objects.all()
print(request.data)
#多个数据加many=True
ser = Bookserializer(instance=book_list, many=True)
return Response(ser.data)
class BookDetView(APIView):
def get(self, request,pk):
book = models.Book.objects.filter(pk=pk).first()
bookser = Bookserializer(book) #many 多个数据加
return Response(bookser.data)
Django2默认支持以下5个转化器:
str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
int,匹配正整数,包含0。
slug,匹配字母、数字以及横杠、下划线组成的字符串。
uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)