RESTful API
一、介绍
RESTful API(即:Representational State Transfer),中文意思是‘表征状态转移’或‘表现层状态转化’,面向资源编程,是目前最流行的一种互联网软件架构。它结构清晰、符合标准、易于理解、扩展方便,所以正得到越来越多网站的采用
二、RESTful设计(规范)
2.1 API与用户的通信协议
总是使用HTTPS协议
http与HTTPS的异同:前者不经过加密,直接原文显示传输,数据的安全性极低;后者是经过SSL/TLS加密的,数据的安全性极高
2.2 域名
https://api.example.com 尽量将API部署在专用域名(会存在跨域问题)
https://example.org/api/ API很简单(推荐使用)
eg:写一个查询所有图书的api接口:
- https://api.example.com/books
- https://127.0.0.1/api/books(推荐使用)
2.3 版本
每个接口都应该有版本
- 放在URL中,如:
- https://api.example.com/v1/
- https://127.0.0.1/api/v2/books/(推荐用这种)
- 将版本信息放在请求头中,请求头 跨域时,引发发送多次请求
2.4 路径
可以将网络上任何东西都看作是资源,如:一本书,一只动物,一个人等等,都是资源,所以都使用名词表示(可以是复数形式)
eg:
https://api.example.com/v1/people https://api.example.com/v1/animals https://api.example.com/v1/employees 不推荐的写法,如下: 获取所有图书:https://127.0.0.1/api/get_all_books 新增一本书:https://127.0.0.1/api/add_book
2.5 method
GET :从服务器取出资源(一项或多项) POST :在服务器新建一个资源 PUT :在服务器更新资源(客户端提供改变后的完整资源) PATCH :在服务器更新资源(客户端提供改变的属性) DELETE:从服务器删除资源
2.6 过滤
通过在url上传入参的形式传递搜索条件,如:
https://api.example.com/v1/books?offset=10:指定返回记录的开始位置
2.7 状态码
200 OK [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 201 CREATED [POST/PUT/PATCH]:用户新建或修改数据成功。 202 Accepted [*]:表示一个请求已经进入后台排队(异步任务) 204 NO CONTENT [DELETE]:用户删除数据成功。 400 INVALID REQUEST [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 401 Unauthorized [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 406 Not Acceptable [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 410 Gone [GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
也可以自定义状态码,如:
status:
-
- 100表示成功
- 101表示用户名密码错误
- 102。。。
2.8 错误处理
状态码是4xx时,应返回错误信息
{ error: "Invalid API key" }
2.9 返回结果
针对不同操作,服务器向用户返回的结果应该符合以下规范
GET /collection:返回资源对象的列表(数组) GET /collection/resource:返回单个资源对象 POST /collection:返回新生成的资源对象 PUT /collection/resource:返回完整的资源对象 PATCH /collection/resource:返回完整的资源对象 DELETE /collection/resource:返回一个空文档
2.10 Hypermedia API
RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,这样用户不用查文档,也知道下一步。
{"link": { "rel": "collection https://www.example.com/zoos", "href": "https://api.example.com/zoos", "title": "List of zoos", "type": "application/vnd.yourformat+json" }}
三、基于Django REST Framework 框架实现 RESTful API
3.1 Postman 软件使用
该软件可以模拟浏览器发送各种请求
- 首先下载安装,下载页面https://www.getpostman.com/apps
- 接着启动软件,注册账号,也可以选择不注册进入使用
3.2 写一个简易的书籍管理(单表)
- 用继承View的方法写
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/$', views.Book.as_view()), url(r'^book/(?P<pk>\d+)', views.Book.as_view()), ]
from django.shortcuts import render from django.http import JsonResponse from django.views import View from app01 import models import json # Create your views here. class Book(View): # 获取所有的书籍信息 def get(self, request): response = {'status': 100, 'data': None} books = models.Book.objects.all() # 构造出所有书籍字典的列表 book_list = [{'name': book.name, 'price': book.price} for book in books] response['data'] = book_list return JsonResponse(response, safe=False) # 修改书籍信息 def put(self, request, pk): data = json.loads(str(request.body, encoding='utf-8')) name = data.get('name') price = data.get('price') models.Book.objects.filter(pk=pk).update(name=name, price=price) return JsonResponse({'status': 100, 'msg': '修改成功'}) # 增加书籍信息 def post(self, request): name = request.POST.get('name') price = request.POST.get('price') models.Book.objects.create(name=name, price=price) return JsonResponse({'status': 100, 'msg': '修改成功'}) # 删除书籍信息 def delete(self, request, pk): models.Book.objects.filter(pk=pk).delete() return JsonResponse({'status': 100, 'msg': '修改成功'})
- 用继承APIView的方法写
首先需要安装drf(django rest framework)框架,它是一个app,所以使用之前要在settings里面进行注册
安装:pip install djangorestframework;注册:在 INSTALLED_APPS 里添加 'rest_framework',
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^book/$', views.Book.as_view()), url(r'^book/(?P<pk>\d+)', views.Book.as_view()), ]
from rest_framework.views import APIView class Book(APIView): # 查询所有的书籍信息 def get(self, request): response = {'status': 100, 'data': None} books = models.Book.objects.all() # 构造出所有书籍字典的列表 book_list = [{'name': book.name, 'price': book.price} for book in books] response['data'] = book_list return JsonResponse(response, safe=False) # 增加书籍信息 def post(self, request): name = request.data['name'] price = request.data['price'] models.Book.objects.create(name=name, price=price) return JsonResponse({'status': 100, 'msg': '修改成功'}) # 修改书籍信息 def put(self, request, pk): # data = json.loads(str(request.body, encoding='utf-8')) name = request.data['name'] price = request.data['price'] models.Book.objects.filter(pk=pk).update(name=name, price=price) return JsonResponse({'status': 100, 'msg': '修改成功'})
注意点:
- APIView中的request对象,不是原来django中的request对象,它是rest_framework.request下的Request,即:rest_framework.request.Request
- 而之前的request是:django.core.handlers.wsgi.WSGIRequest
- 取值方式的改变,APIView中都在request.data里面取值,只是编码格式的不同
- 前端传过来的编码格式是json格式:{'key': 'value', 'key': 'value'}
- 前端传过来的编码格式是urlencoded格式:<QueryDict: {'key': ['value'], 'key': ['value']}>
本文来自博客园,仅供参考学习,如有不当之处还望不吝赐教,不胜感激!转载请注明原文链接:https://www.cnblogs.com/rong-z/p/10097710.html
作者:cnblogs用户