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接口:

  1. https://api.example.com/books
  2. https://127.0.0.1/api/books(推荐使用)

2.3 版本

每个接口都应该有版本

  • 放在URL中,如:
  1. https://api.example.com/v1/
  2. 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 软件使用

该软件可以模拟浏览器发送各种请求

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()),
]
urls.py
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': '修改成功'})
views.py

  • 用继承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()),
]
urls.py
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': '修改成功'})
views.py
注意点:
  • 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']}>

 

posted @ 2018-12-10 17:26  cnblogs用户  阅读(189)  评论(0编辑  收藏  举报