2020-12-1402 drf之restful规范,序列化组件,Request类

昨日回顾

1、web开发模式

-前后端混合开发
-前后端分离开发

2、api接口

3、postman的使用(莫伊发送http请求的工具)

-对地址要求严格
-携带get数据
-携带post数据(格式)
-携带请求头

4、drf:djangorestframework是一个django的一个app,更快速的在django框架上的写接口

-pip3 install djangorestframework

今日内容

1、restful规范

-1)、REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer:表征性状态转移
    REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
    所有的数据,不过是通过网络获取的还是操作(增删查改)的数据,都是资源,将一切数据视为资源,是REST区别于其他架构风格的最本质的属性
    对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构
-2)、web API接口的设计风格,尤其适用于前后端分离的应用模式中
-3)、于语言,平台无关,任何框架都可以写出符合restful规范的api接口
-4)、规范:10条
    -1、数据的安全保障:url链接一般都采用http协议进行传输
    -2、接口特征表现:api关键字标识
        -API与用户的通信协议,总是使用https协议 ,也即是加密传输 详情:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
        -https://api.baidu.com/books/
        -https://www.baidu.com/api/books/
    -3、多版本共存:url链接中标识接口版本
        -https://api.baidu.com/v1/books/
        -https://api.baidu.com/v2/books/
    -4、数据即是资源,军使用名词(可复数)
        -接口一般都是完成前台数据的交互,交互的数据我们称之为资源
        -一般提倡用医院的附属形式,不要用动词
        -查询所有图书
            -https://api.baidu.com/books/
            -https://api.baidu.com/get_all_books/  #错误示范
            -https://api.baidu.com/delete_user/  #错误示范
            -https://api.baidu.com/user/  #删除用户的示例,疑问一下,这到底是删还是查?可以通过请求方式来区分
    -5、资源操作由请求方式决定:
        -https://api.baidu.com/books/    # get请求:获取所有书
        -https://api.baidu.com/books/1    # get请求:获取主键为1的书
        -https://api.baidu.com/books/    # post请求:新增一本书
        -https://api.baidu.com/books/1   # put请求:整体修改主键为1的书
        -https://api.baidu.com/books/1   # patch请求:局部修改主键为1的书
        -https://api.baidu.com/books/1   # delete请求:删除主键为1的书
    -6、过滤。通过url上传参的形式传递搜索条件
        -https://api.example.com/v1/zoos?limit=10  # 指定返回记录的数量
        -https://api.example.com/v1/zoos?offset=10&limit=3  # 指定记录开始的位置
        -https://api.example.com/v1/zoos?page=2&per_page=100  # 指定第几页,以及每页的记录数
        -https://api.example.com/v1/zoos?sortby=name&order=asc  # 指定返回结果按照哪个属性排序,以及排序的顺序
        -https://api.example.com/v1/zoos?animal_type_id=1  # 指定筛选条件
    -7、响应状态码
        -返回数据中带状态码
        -{'code':100}
    -8、返回结果中带错误信息
        -{'code':100,'msg':'失败的原因'}
    -9、服务器向用户的返回结果,该符合一下规范
        GET/collection:返回资源对象的列表(数组)
        GET/collection/resource:返回单个资源对象(字典)
        POST/collection:返回新生成的资源对象(新增后的对象字典)
        PUT/collection/resource:返回完整的资源对象(修改后的对象字典)
        PATCH/collection/resource:返回完整的资源对象(修改后的对象字典)
        DELETE/collection/resource:返回一个空文档
    -10、返回的数据中带链接地址,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。
        -查询id为1的图书接口,返回结果示例
        {'code':100,
         'msg':'成功',
         'result':
             {'title':'金瓶梅',
              'price':12.3,
              'publish':'https://127.0.0.1/api/v1/publish/3'
             }
        }

2、APIview源码分析

-1 APIview的as_view
    -内部还是执行了View的闭包函数view
    -禁用掉了csrf
    -一切皆对象,函数也是对象  函数地址.name=lqz
-2 原生View类中过的as_view中的闭包函数view
    -本质执行了self.dispatch(request, *args, **kwargs),执行的是APIView的dispatch
-3 APIView的dispatch
    def dispatch(self, request, *args, **kwargs):
        # DRF的Request类的对象,内部有request._request,是原生request
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request

        try:
            self.initial(request, *args, **kwargs)
            '''
            #认证,权限,频率
            self.perform_authentication(request)
            self.check_permissions(request)
            self.check_throttles(request)
            '''
            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)
        # 把视图函数(类)返回的response,又包装了一下
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

3、Request类分析

rest framework 传入视图的request对象不再是django默认的HttpRequest对象,而是REST framework提供的扩展了HttpRequest类的Request类的对象。
REST framework 提供了Parser解析器,在接收到请求后会自动根据content-type指明的请求数据类型(JSON,表单等)将请求数据进行parser解析,解析为类字典【QueryDict】
对象保存到Request对象中。
Request对象的数据是自动根据前端发送的数据的格式进行解析之后的结果。
无论前端发送哪中格式的数据,我们都可以以统一的方式读取数据。

-1)、Request类
    -request._request : 原生request
    -request.data : 返回解析之后的请求体数据, post请求提交的数据(urlencoded,json,formdata)request.POST里只能取urlencoded和formdata两种格式的数据
    -request.query_params : 原生的request.GET,为了遵循restful规范,换壳更准正确的名字而已。
    -request.FILES:新的
    -重写了__getattr__,新的request.原来私有·所有的属性和方法,都能直接拿到
         def __getattr__(self, attr):
            return getattr(self._request, attr)

4、序列化组件介绍

-作用:
-1、序列化,序列化器会把模型对象转换成字典,经过response以后变成json字符串
    -Book--序列化器--》字典--通过drf:Response-->json格式字符串---》传给前端
-2、反序列化,把客户端发送过来的数据,经过request以后变成字典,序列化器可以把字典转成模型
    -json格式数据---drf:Request==》字典--序列化器---Book
-3、反序列化,完成数据校验功能

5 序列化组件简单使用

1 序列化的使用

-写一个序列化类继承serializers.Serializer
-在类中写要序列化的字段
-在视图类中,实例化得到一个序列化类的对象,把要序列化的数据传入
    ser=BookSerializer(instance=res,many=True)
-得到字典
    ser.data就是序列化后的字典

5.1、代码实现

serializer.py

from rest_framework import serializers
class BookSerializer(serializers.Serializer):
    # 要序列化哪个字段
    id=serializers.IntegerField()
    # id=serializers.CharField()
    title=serializers.CharField(max_length=32)
    price=serializers.DecimalField(max_digits=5, decimal_places=2)
    # publish=serializers.CharField(max_length=32)

models.py

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish = models.CharField(max_length=32)

views.py

from app01 import models
from app01.serializer import BookSerializer
class Book(APIView):
    def get(self,request,*args,**kwargs):

        res=models.Book.objects.all()
        # 借助序列化器
        # 如果是多条,就是many=True
        # 如果是单个对象,就不写
        ser=BookSerializer(instance=res,many=True)
        # 通过序列化器得到的字典
        # ser.data
        print(ser.data)
        return Response(ser.data)

urls.py

path('books/', views.Book.as_view()),

6 序列化类字段类型和字段参数

字段类型(记列的这几个)

-IntegerField
-CharField
-DecimalField
-DateTimeField
-。。。跟models中大差不差

常用字段参数

-选项参数
    max_length  最大长度
    min_lenght  最小长度
    allow_blank 是否允许为空
    trim_whitespace 是否截断空白字符
    max_value   最小值
    min_value   最大值

-通用参数
    #重点
    read_only   表明该字段仅用于序列化输出,默认False
    write_only  表明该字段仅用于反序列化输入,默认False

    # 掌握
    required    表明该字段在反序列化时必须输入,默认True
    default     反序列化时使用的默认值
    allow_null  表明该字段是否允许传入None,默认False

    # 了解
    validators  该字段使用的验证器
    error_messages  包含错误编号与错误信息的字典

7 序列化器的保存功能

如果序列化类继承的是Serializer,必须重写create方法

使用方式

-视图类
 def post(self, request):
    print(request.data)
    ser = BookSerializer(data=request.data)
    if ser.is_valid():
        ser.save()  # 保存到数据库中
        return Response(ser.data)
    else:
        # 没有校验通过的错误信息
        return Response(ser.errors)
-序列化类
class BookSerializer(serializers.Serializer):
    ...

    def create(self, validated_data):
        # 为什么要重写create?
        res=models.Book.objects.create(**validated_data)
        print(res)
        return res

8 序列化器的字段校验功能

三种方式

-字段自己的校验规则(max_length...)
-validators的校验
    publish = serializers.CharField(max_length=32,validators=[check,])

    def check(data):
    if len(data)>10:
        raise ValidationError('最长不能超过10')
    else:
        return data
-局部和全局钩子
    # 局部钩子,validate_字段名,需要带一个data,data就是该字段的数据
def validate_title(self, data):
    if data.startswith('sb'):
        raise ValidationError('不能以sb开头')
    else:
        return data
# 全局钩子
def validate(self, attrs):
    title=attrs.get('title')
    publish=attrs.get('publish')
    if title==publish:
        raise ValidationError('书名不能跟出版社同名')
    else:
        return attrs

9 read_only和write_only

read_only   表明该字段仅用于序列化输出,默认False
write_only  表明该字段仅用于反序列化输入,默认False


class BookSerializer(serializers.Serializer):
    # 要序列化哪个字段
    id = serializers.IntegerField(required=False)
    # id=serializers.CharField()
    title = serializers.CharField(max_length=32,min_length=2,read_only=True)
    price = serializers.DecimalField(max_digits=5, decimal_places=2)
    # 序列化的时候看不到
    publish = serializers.CharField(max_length=32,validators=[check,],write_only=True)

你可能感兴趣的:(2020-12-1402 drf之restful规范,序列化组件,Request类)