10. REST & ECharts

django-restful是一个为django提供的,让django能够方便提供API接口服务的第三方框架。

Django-RESTful官方网站

有了RESTful设计,服务器程序就能更好的进行前后端分离设计,服务器部分只负责处理数据,一般采用json格式, 而前端只需要负责展示部分即可。

前后端分离设计可以看作是把django中的模板部分单独独立出来,可以使用任何前端技术, 而后端只负责处理数据和数据交互即可。

10.1. RESTful概述

一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互 类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。

10.2. 设计指南

  • 使用名词表示资源

  • 关注请求头

    • GET:
      • 请求指定的页面信息,并返回实体主体
      • GET请求请提交的数据放置在HTTP请求协议头中
      • GET方法通过URL请求来传递用户的输入,
      • GET方式的提交你需要用Request.QueryString来取得变量的值。
      • GET方法提交数据,可能会带来安全性的问题,数据被浏览器缓存。
      • GET请求有长度限制。
    • HEAD:
      • 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头。
    • POST:
      • 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。
      • POST请求可能会导致新的资源的建立和/或已有资源的修改。
      • POST方式提交时,你必须通过Request.Form来访问提交的内容
    • PUT:
      • 从客户端向服务器传送的数据取代指定的文档的内容。
    • DELETE:
      • 请求服务器删除指定的页面。
      • DELETE请求一般返回3种码
        • 200(OK): 删除成功,同时返回已经删除的资源。
        • 202(Accepted): 删除请求已经接受,但没有被立即执行(资源也许已经被转移到了待删除区域)。
        • 204(NoContent): 删除请求已经被执行,但是没有返回资源(也许是请求删除不存在的资源造成的)。
    • CONNECT:
      • HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。
    • OPTIONS:
      • 获取服务器支持的HTTP请求方法;也是黑客经常使用的方法。
      • 用来检查服务器的性能, 例如:AJAX进行跨域请求时的预检,需要向另外一个域名的资源发送一个HTTP OPTIONS请求头,用以判断实际发送的请求是否安全。
      • 该请求方法的响应不能缓存。
    • TRACE:
      • 回显服务器收到的请求,主要用于测试或诊断。
  • 使用习惯

    • 分页情况

        # 不太好的例子,没有分页信息
        Status:200 OK
        [
            { "id":1,
              "url": "http://baoshu.red/mypost/1",
            },
      
            { "id":2,
              "url": "http://baoshu.red/mypost/2",
            },
        ]
      
        # 正确信息
        Status:200 OK
        X-Togal-Count: 213
        Link:<http://liuying.name/mypost?page=2>; rel="next",
             <http://liuying.name/mypost?page=2>; rel="last"
        [
            { "id":1,
              "url": "http://liuying.name/mypost/1",
            },
      
            { "id":2,
              "url": "http://liuying.name/mypost/2",
            },
        ]
      
    • 201 created 相应应该带有新资源Location

    • 405 Method Not Allowed相应,应该带有Allow头

    • 对输出结果不过渡包装

        HTTP/1.1 200 OK
        {
             'success':true,
             'data':{ 'id':1, 'name':'liuying'),
        }
        # 替代例子
        HTTP/1.1 200 OK
        { 'id':1, 'name':'liuying'),
      
    • 版本控制

      • 在URI中显示(提倡), http://api.liuying.com/api/v2
      • 放在请求头(GitHub), Accept:application/vnd.github.v3+json
      • 自定义请求头(不推荐), X-Api-Version:1

10.3. 序列化/反序列化

10.3.1. 名词解释

  • 序列化就是指把程序对象转换为字节序列的过程, 是models->json->bytes过程
  • 反序列化就是指把字节序列恢复为程序对象的过程, 是序列号的逆过程
  • 序列化最重要的作用:
    • 在传递和保存对象时.保证对象的完整性和可传递性
    • 对象转换为有序字节流,以便在网络上传输或者保存在本地文件中
  • 反序列化的最重要的作用:
    • 根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。
  • 核心作用就是对象状态的保存和重建。(整个过程核心点就是字节流中所保存的对象状态及描述信息)

10.3.2. json/xml的数据传递:

远程信息传输一般采用json/xml格式

  • 在数据传输(也可称为网络传输)前,先通过序列化工具类将对象序列化为json/xml文件
  • 在数据传输(也可称为网络传输)后,再将json/xml文件反序列化为对应语言的对象

10.3.3. 序列化优点:

  • 将对象转为字节流可以存储到硬盘上,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。
  • 序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。
  • 通过序列化可以在进程间传递对象。

10.3.4. 序列化算法需要做的事:

  • 将对象实例相关的类元数据输出
  • 递归地输出类的超类描述直到不再有超类
  • 类元数据输出完毕后,从最顶端的超类开始输出对象实例的实际数据值。

10.4. Django_Rest FrameWork

django restuframework为django项目提供restful支持,让django项目能快速提供API 支持。

如果为后台框架提供API支持,最核心的功能应该是快速的序列化和反序列化。

10.5. 教学案例

  1. 创建项目v7_api

  2. 创建工程tuling_rest

  3. 编写models文件中的类,包括Student, Room

    # tuling_rest/models.py
    class Student(models.Model):
        name = models.CharField(max_length=20, default="NoName")
        age = models.IntegerField(default=18)
        score = models.IntegerField(default=60)
    
    
    class Room(models.Model):
        name = models.CharField(max_length=20)
        room_id = models.CharField(max_length=10, default="00000")
        stu_amount = models.IntegerField(default=0)
        location = models.CharField(max_length=50)
        desc = models.CharField(max_length=200)
    
  4. 设置settings.py

     INSTALLED_APPS = [
     ... ...
     'rest_framework', #Rest框架
     'tuling_rest',
     ]
    
     #对DRF进行配置,不需要就不用1
     REST_FRAMEWORK = {
         'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
         'PAGE_SIZE': 2
     }
    
  5. 添加文件tuling_rest/serializers.py

    #从drf库中导入序列化模块
    from  rest_framework import serializers
    from .models import Student, Room
    
    class StudentSerializer(serializers.ModelSerializer):
        '''
        序列化的时候,可以用单个model实例来初始化,也可以用queryset对象实例化,但需要设置many=True
        '''
        class Meta:
            # 这个用来序列化Student模型
            model = Student
            #只序列化模型中的两个属性:name,score
            fields = ("name", "score")
    
        '''
        实现create和update函数
        '''
        #如果是是创建类型的请求,则调用这个
        def create(self, validated_data):
            return Student.objects.create(**validated_data)
    
        #如果是更新类型的请求
        def update(self, instance, validated_data):
            instance.name = validated_data.get('name', instance.name)
            instance.age = validated_data.get('age', instance.age)
            instance.score = validated_data.get('score', instance.score)
            instance.save()
            return instance
    
    class RoomSerializer(serializers.ModelSerializer):
        class Meta:
            model = Room
            fields = ("room_id", "stu_amount")
    
  6. 编写视图函数
    编写DRF的视图的时候,一般我们建议使用DRF自带的一些视图类,具体请参看代码

  7. 修改路由v1_api/urls.py

  8. 迁移数据库

  9. 编写测试test01,对基本Serializer进行测试

  • 权限
    • 建立permissions.py
    • 添加权限IsMe
    • 在视图中导入IsMe并使用