目录
1. Http协议
1.1 简介
HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于万维网(WWW:World Wide Web )服务器与本地浏览器之间传输超文本的传送协议。
HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
应用层:基于tcp/ip之上,用于网络传输,广泛应用前后端的交互
1.2 四大特性
1. 基于请求响应
2. 基于TCP/IP之上用于应用层的协议
3. 无状态
4. 无/短连接
1.3 请求数据格式
1. 请求首行: 请求方式get,post, 请求地址:get携带数据,请求协议版本:0.9/1.1/2.x
2. 请求头:key:value
Cookie:这是最重要的请求头信息之一
Accept:浏览器可接受的MIME类型。
Host:初始URL中的主机和端口
From:请求发送者的email地址,由一些特殊的Web客户程序使用,浏览器不会用到它。
Date 当前的GMT时间。你可以用setDateHeader来设置这个头以避免转换时间格式的麻烦。
3. 请求体:post请求携带数据:三种编码格式
1. Content-Type:application/x-www-form-urlencoded ajax默认的数据格式,请求体中的数据以json字符串的形式发送到后台
2. Content-Type:application/json;charset=utf-8 axios默认的数据格式,请求中的数据会以普通表单形式发送到后端
3. Content-Type:multipart/from-data 他会将请求体的数据处理为一条消息,以标签为单元,用分隔符分开,既可以上传键值对,也可以上传文件
1.4 响应数据格式
1. 响应首行:响应协议版本,状态码,状态描述字符串
1XX: 信息性状态码,接收的请求正在处理
2XX:成功状态码, 请求正常处理完毕
3XX: 重定向状态码,需要进行附加操作以完成请求
4XX: 客户端错误状态码, 服务器无法处理请求
5XX: 服务器错误状态码, 服务器处理请求出错
2. 响应头:key:value
Allow: 服务器支持哪些请求方法
Content-Length: 响应体的字节长度
Content-Type: 响应体的MIME类型
Content-Encoding: 设置数据使用的编码类型
Date: 设置消息发送的日期和时间
3. 响应体:浏览器里看到的东西
服务端返回数据 html格式,json格式
1.5 http协议版本区别
1. HTTP 0.9是最初的HTTP协议
每个http请求都是一个tcp的链接
只支持GET请求
没有协议头
无状态性
只能传输超文本
2. HTTP 1.0
新增了POST和HEAD命令
可以设置contentType传输多种数据格式
新增状态码,权限,内容编码等
3. HTTP 1.1 目前最流行
keep-alvie,多个http请求可以使用同一个tcp
请求和响应都支持Host头域,认为每一个服务器都绑定唯一的一个IP地址。
4. HTTP 2.0
增加双工模式,提高利用率
服务端推送:不经请求向客户端发送数据
二进制分帧层
头信息压缩机制
2. APIView基本使用
1. 什么是rest_framework
它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架。
安装方式有很多种,可以通过pip,或者在pycharm中安装也可以
2. APIView
drf:是一个第三方的app,只能在djagno上使用,安装了drf后,导入一个视图类APIView,所有后期要使用drf写视图类,都是继承APIView及其子类.
它的作用和from django.views import View中的View作用差不多,APIView是继承了View,所以执行as_view,dispatch方法都会
先走到APIView这个类中。所以通过这个APIView里的dispatch进行一层封装,对request这个对象进行改变,添加了认证、权限、频率这些
2.1 获取图书接口使用View+JsonResponsexie
views
from django.shortcuts import render
from django.http import JsonResponse
# Create your views here.
from django.views import View
from .models import Book
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}) # 只能序列化字典与列表
urls
from app01.views import BookView
urlpatterns = [
path('admin/', admin.site.urls),
path('books/', BookView.as_view()),
]
2.2 使用APIView+drf的Response
views
# dir帮我们封装了请求类,响应类,路由类,视图类
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
# APIView继承自django的View
class BookView(APIView):
def get(self, request):
book_list = Book.objects.all()
res_list = []
for book in book_list:
res_list.append({'name': book.name, 'price': book.price, 'publish': book.publish})
return Response(res_list)
3. 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的校验了
# all other authentication is CSRF exempt.
# 去掉csrf,在函数上加装饰器
# @csrf_exempt
# def index(request):
# pass
# 本质等同于 index=csrf_exemot(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
3.1 总结
1. 只要继承APIView都没有csrf的认证了
2. 以后视图类中使用的request对象,已经变成了drf提供的Request类的对象了
3. 执行视图类的方法之前,执行了3大认证(认证,权限,频率)
4. 在执行三大认证和视图类的方法过程中只要报错,都会被捕获处理
3.2 验证APIView的使用
1. 视图类中使用的request对象,已经变成了drf提供的Request类的对象了
原生djiango 的request是这个类的对象:
<class 'django.core.handlers.wsgi.WSGIRequest'>
drf的request是这个类的对象:
<class 'rest_framework.request.Request'>
<class 'rest_framework.request.Request'>
2. request已经不是原来的request了,还能像原来的request一样使用吗?
用起来 像之前一样
print(request.method) # get
print(request.path) # /books/
print(request.GET) # 原来的get请求提交的参数
print(request.POST) # 原来post请求提交的参数
4. Request的源码分析:rest_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)
以后用的所有属性或方法,直接用就可以了---》(通过反射去原来的request中取的)
新的request内部有个老的request,就是 request._request
data 是个方法,被property装饰了,变成了数据属性用
以后body体中提交的数据,都从这里取(request.POST)
urlencoded,form-data:提交的数据在request.POST中
json格式提交的数据,在requets.POST中没有,它在request.body中
现在无论那种格式,都从request.data中取
query_params:get请求提交的参数,等同于request._request.GET 或 request.GET
其他:取文件也是从request.FILES中取,跟之前一样
原生requets.POST 只有urlencoded和form-data格式提交的数据,json格式提交的数据在body中,拿出来自己处理,但是drf的request中有个data,data中可以取到任意编码提交的数据
request.data 有时候是(urlencoded,form-data)QueryDict,有时候(json)是字典
4.1 什么是魔法方法
1 在类中只要以__开头,__结尾的都称之为魔法方法
2 这种方法不需要手动调用,某种情况会自动触发
3 eg: __init__,__str__,__call__,......
5. 序列化
5.1 序列化组件介绍
是什么?drf提供的一个类,我们继承它,写自己的类
有什么用?就是用来序列化qs或单个对象的
获取所有图书接口--> qs,单个book对象转成json格式字符串,给前端--> 序列化,使用for循环,列表套字典拼接的
drf提供了一种可以快速实现序列化的类:序列化类
1. 序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
2. 反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
3. 反序列化,完成数据校验功能
5.2 序列化组件基本使用
5.2.1 定义一个序列化类
serializer
# 写序列化类,给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() # 字段类
5.2.2 使用序列化类,序列化多条数据
views
# 写序列化类:给book进行序列化
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from .serializer import BookSerializer
class BookView(APIView): # APIView继承自django的view
def get(self,request):
book_list = Book.objects.all()
# instance表示要序列化的数据,mang=True表示序列化多条(instance是qs对象,一定要传many=True)
ser = BookSerializer(instance=book_list, many=True)
return Response(ser.data)
5.2.3 使用序列化类,序列化单挑数据
class BookDetailView(APIView):
def get(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book)
return Response(ser.data)
path('books/<int:pk>/', BookDetailView.as_view()),
5.3 反序列化
5.3.1 新增视图类
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)
序列化类
# 写序列化类,给book进行序列化
# from rest_framework.serializers import Serializer
from rest_framework import serializers
from .models import Book
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
5.3.2 修改视图类
class BookDetailView(APIView):
def put(self, request, pk):
book = Book.objects.filter(pk=pk).first()
ser = BookSerializer(instance=book, data=request.data)
if ser.is_valid():
ser.save()
return Response(ser.data)
else:
return Response(ser.errors)
序列化类
from rest_framework import serializers
from .models import Book
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
5.3.3 删除
class BookDetailView(APIView):
def delete(self, instance, pk):
Book.objects.filter(pk=pk).delete()
return Response()
标签:02,APIView,self,request,book,序列化,data
From: https://www.cnblogs.com/cainiaozhy/p/16732563.html