# REST & ECharts django-restful是一个为django提供的,让django能够方便提供API接口服务的第三方框架。 [Django-RESTful官方网站](https://www.django-rest-framework.org/) 有了RESTful设计,服务器程序就能更好的进行前后端分离设计,服务器部分只负责处理数据,一般采用json格式, 而前端只需要负责展示部分即可。 前后端分离设计可以看作是把django中的模板部分单独独立出来,可以使用任何前端技术, 而后端只负责处理数据和数据交互即可。 - 虚拟环境下安装: - pip install djangorestframework - 测试发送端: - 火狐使用RestClient和HttpRequester, 因为火狐新版本问题可能已经停用 - 使用[postman](http://www.postman.com) - 也可以使用 [httpie](http://www.mycode.wang/t/OwLnQ7oyg) - 新出了一个[postwoman](https://postwoman.io/), 据说很好用,请轻松胜过postman, :) - 参看文章 - [利用 Django REST framework 编写 RESTful API](http://www.mycode.wang/t/DlL3Vaeyn) - [Django Rest Fr4amework 序列化](http://www.mycode.wang/t/bvEwqmRLJ) - [RESTful API 编写指南](http://www.mycode.wang/t/pQEqkMzLz) ## RESTful概述 一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互 类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。 2000 年 Roy Fielding 的博士论文中,他是 HTTP 规范的主要编写者之一。 ## 设计指南 - 使用名词表示资源 - 关注请求头 - 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:; rel="next", ; 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 ## 序列化/反序列化 ### 名词解释 - 序列化就是指把程序对象转换为字节序列的过程, 是models->json->bytes过程 - 反序列化就是指把字节序列恢复为程序对象的过程, 是序列号的逆过程 - 序列化最重要的作用: - 在传递和保存对象时.保证对象的完整性和可传递性 - 对象转换为有序字节流,以便在网络上传输或者保存在本地文件中 - 反序列化的最重要的作用: - 根据字节流中保存的对象状态及描述信息,通过反序列化重建对象。 - 核心作用就是对象状态的保存和重建。(整个过程核心点就是字节流中所保存的对象状态及描述信息) ### json/xml的数据传递: 远程信息传输一般采用json/xml格式 - 在数据传输(也可称为网络传输)前,先通过序列化工具类将对象序列化为json/xml文件 - 在数据传输(也可称为网络传输)后,再将json/xml文件反序列化为对应语言的对象 ### 序列化优点: - 将对象转为字节流可以存储到硬盘上,把序列化的对象,通过反序列化为原来的对象,并且序列化的二进制序列能够减少存储空间(永久性保存对象)。 - 序列化成字节流形式的对象可以进行网络传输(二进制形式),方便了网络传输。 - 通过序列化可以在进程间传递对象。 ### 序列化算法需要做的事: - 将对象实例相关的类元数据输出 - 递归地输出类的超类描述直到不再有超类 - 类元数据输出完毕后,从最顶端的超类开始输出对象实例的实际数据值。 ## Django_Rest FrameWork django restuframework为django项目提供restful支持,让django项目能快速提供API 支持。 如果为后台框架提供API支持,最核心的功能应该是快速的序列化和反序列化。 ## 教学案例 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` 4. 迁移数据库 5. 编写测试test01,对基本Serializer进行测试 - 权限 - 建立permissions.py - 添加权限IsMe - 在视图中导入IsMe并使用