回顾补充知识
-
http请求
-
应用层:基于tcp/ip之上
-
是进行网络传输,广泛用于前后端的交互
-
请求协议:
-
请求首行
请求方式 :get、post,请求地址:get携带数据,请求协议,请求版本:
0.9/1.1/2.x
-
请求头:
key:value
-
请求体
post
请求携带数据:三种编码格式
-
-
响应协议
-
响应首行
响应协议版本,状态码,状态描述字符串
-
响应头
携带 cookie
-
响应体
浏览器里面可以看到的东西
- html格式
- json格式
-
-
-
drf快速使用
pip3 install djangorestframework
所有接口:本质都是5个接口及其变型
-
View执行流程,源码分析
-
cbv
都要继承View
>>>路由写法变成>>>视图类.as_view()
>>> 在视图类中写get,post, delete
-
路由:
视图类.as_view()
>>> 执行结果是个函数内存地址
,请求来了,路由匹配成功,就会执行视图类.as_view()(request)
-
视图函数
(View)
的as_view
类的绑定方法,本质路由就放了view函数
的内存地址 -
请求来了执行
view(request)
>>>本质又执行了self.dispatch(request, *args, **kwargs)
-
视图类找
dispatch
,View
的dispatch
-
核心代码
if request.method.lower() in self.http_method_names: # 反射:通过字符串去对象中找属性或方法 #handler就是TestView中的get方法 handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request, *args, **kwargs) # get(request)
-
-
restful规范----10条
- http:传输安全
- 地址中国带有api标识
- 地址中带有版本号
- 请求地址用名词,复数表示
- 通过请求方式区别获取资源的方式
- 响应状态码:http 自定义状态码
- 响应带有错误信息
- 请求带过滤条件
- 响应中带地址
- 返回数据符合条件如下规范:
- 查所有 数组、列表
- 查单个:对象
- 删除:空白档
-
http协议版本区别
- 0.9:每个http请求都是一个tcp的链接
- 1.1:keep-alive,多个http请求可以使用同一个tcp
- 2.x:同一个tcp的包,可能是多个http请求,多路复用
-
你知道的http请求头有哪些?
今日学习内容
APIView基本使用
drf
,是一个第三方的app
,只能在django
上使用- 安装
drf
后,导入一个视图类APIView
,所有后期要使用drf
写视图类,都是继承APIView
及其子类
使用View + JsonResponse
class BookView(View):
def get(self, request):
print(type(request))
book_list = Book.objects.all()
# book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return JsonResponse(res_list,safe=False,json_dumps_params={'ensure_ascii':False}) # 只能序列化字典和列表,
使用APIView + drf 的Response
-
要先将
rest_framework
注册settings.py
到这个app
中这样才可以观察到好看的请求响应的信息
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
class BookView(APIView): # APIView继承自django的View
def get(self, request):
# print(type(self.request)) # 新的request
# print(type(request))
print(request._request)
print(type(request._request)) #django.core.handlers.wsgi.WSGIRequest
# print(request.method) # get
# print(request.path) # /books/
# print(request.GET) # 原来的get请求提交的参数
# print(request.POST) # 原来post请求提交的参数
book_list = Book.objects.all()
# book_list是queryset对象不能直接序列化,只能通过for循环一个个拼成列表套字典的形式
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return Response(res_list)
APIView源码分析
注意:视图类继承APIView后,执行流程就发生了变化,这个变化就是整个的drf的执行流程。
# 一旦继承了APIView入口
-路由配置跟之前继承View是一样的----》找视图类的as_view---》【APIView的as_view】
@classmethod
def as_view(cls, **initkwargs):
# 又调用了父类(View)的as_view
view = super().as_view(**initkwargs)
'''
# 从此以后,所有的请求都没有csrf的校验了
# 在函数上加装饰器
@csrf_exempt
def index(request):
pass
本质等同于 index=csrf_exempt(index)
'''
return csrf_exempt(view)
-请求来了,路由匹配成功会执行 View类的的as_view类方法内的view闭包函数(但是没有了csrf认证),
-真正的执行,执行self.dispatch---->APIView的dispatch 【这是重点】
def dispatch(self, request, *args, **kwargs):
# 参数的request是原来的django原生的request
# 下面的request,变成了drf提供的Request类的对象---》return Request(。。。)
request = self.initialize_request(request, *args, **kwargs)
# self 是视图类的对象,视图类对象.request=request 新的request
self.request = request
try:
# 执行了认证,频率,权限 [不读]
self.initial(request, *args, **kwargs)
# 原来的View的dispatch的东西
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
response = handler(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都没有csrf分认证
- 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象
- 执行视图类的方法之前,执行3大认证(认证,权限,频率)
- 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理
Request类源码分析
-
视图中使用的
request
对象,已经变成了drf
提供的request
类的对象原生django 的request是这个类的对象:django.core.handlers.wsgi.WSGIRequest drf 的request是这个类的对象:rest_framework.request.Request
-
request
已经不是原来的request
了,但是还是可以像原来那样使用print(request.method) # get print(request.path) # /books/ print(request.GET) # 原来的get请求提交的参数 print(request.POST) # 原来post请求提交的参数
-
Resquest
的源码分析:res_framework.request.Request
'类中有个魔法方法:__getattr__ 对象.属性,属性不存在会触发它的执行' def __getattr__(self, attr): # 如果取的属性不存在会去原生django的request对象中取出来 try: #反射:根据字符串获取属性或方法,self._request 是原来的request return getattr(self._request, attr) except AttributeError: return self.__getattribute__(attr)
总结
1.以后用的所有的属性或方法,直接用点的方式就行。(通过反射去原来request中取) 2.新的request内部有个老的request,就是request._request 3.data 是个方法,被property装饰了,变成了数据属性用 request.POST 可以获取body体提交的数据 request.POST 可以获取urlencoded,form-data 提交的数据 json 格式提交的数据,在request.POST中找不到,应该在request.body中找 现在无论哪种格式,都从request.data中取 4.query_params:get请求提交的参数,等同于request._request.GET 或 request.GET 5.取文件也是从request.FILES中取 6. 原生requets.POST 只能获取urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个 data , data 中可以取到任意编码提交的数据。 7. request.data 有时候结果是(urlencoded,form-data)QueryDict,有时候(json)是字典。
-
什么是魔法方法?
1 在类中只要以__开头,__结尾的都称之为魔法方法 2 这种方法不需要手动调用,某种情况会自动触发 3 你学过的: __init__,__str__,__call__,......
序列化组件介绍
drf提供了一种可以快速实现序列化的类:序列化类
序列化组件基本使用
定义一个序列化类
写序列化类:给book进行序列化
# from rest_framework.serializers import Serializer
from rest_framework import serializers
class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类
# price = serializers.CharField()
publish = serializers.CharField()
使用序列化类,序列化多条数据
class BookView(APIView): # APIView继承自django的View
def get(self, request):
book_list = Book.objects.all()
# instance表示要序列化的数据,many=True表示序列化多条(instance是qs对象,一定要传many=True)
ser = BookSerializer(instance=book_list, many=True)
return Response(ser.data)
使用序列化类,序列化单挑数据
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
反序列化(新增,修改)
新增,修改>>>前端传入的数据,要校验>>>序列化类有数据校验功能
新增
视图类
class BookView(APIView): # APIView继承自django的View
def post(self, request):
# 前端传递数据,从request.data取出来
ser = BookSerializer(data=request.data)
if ser.is_valid(): # 表示校验前端传入的数据 没有写校验规则,现在等于没校验
ser.save() # 再写东西,这里会报错 调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
return Response(ser.data)
else:
return Response(ser.errors)
序列化类
class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类
price = serializers.CharField()
publish = serializers.CharField()
# 重写create方法,
def create(self, validated_data):
res = Book.objects.create(**validated_data)
return res
修改
视图类
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
# 前端传递数据,从request.data取出来
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid(): # 表示校验前端传入的数据 没有写校验规则,现在等于没校验
ser.save() # 再写东西,这里会报错 调用save会触发BookSerializer的save方法,判断了,如果instance有值执行update,没有值执行create
return Response(ser.data)
else:
return Response(ser.errors)
序列化类
class BookSerializer(serializers.Serializer):
# 要序列化的字段 有很多字段类,字段类有很多字段属性
name = serializers.CharField() # 字段类
price = serializers.CharField()
publish = serializers.CharField()
# 重写update
def update(self, instance, validated_data):
# instance要修改的对象
# validated_data 校验过后的数据
instance.name = validated_data.get('name')
instance.price = validated_data.get('price')
instance.publish = validated_data.get('publish')
instance.save()
return instance
标签:python,self,request,视图,学习,book,Day64,序列化,data
From: https://www.cnblogs.com/bjyxxc/p/16731620.html