目錄
2-2-1 方式一、將API部署在本站域名內部 - 不推薦,存在跨域問題
2-2-2 方式二、將API部署在域名末尾 - 推薦,使用簡單
2-4-2 方式二、放在請求頭內(不推薦,跨域時會引發多次請求)
2-5-1 冪等性 - 對接口的多次調用所產生的結果和調用一次是一致的
2-6 過濾方式規範 - 通過在url上傳參的形式傳遞搜索條件
2-10 Hypermedia API - 返回結果中提供指向其他API的鏈接
一、RESTful概念 - 一種開發規範
- REST(Representational State Transfer 表徵狀態轉移)與技術無關,代表的是一種軟件架構風格
- REST從資源的角度類審視整個網絡,它將分佈在網絡中某個節點的資源通過URL進行標識,客戶端應用通過URL來獲取資源的表徵,獲得這些表徵致使這些應用轉變狀態
- 所有的數據,不過是通過網絡獲取的還是操作(增刪改查)的數據,都是資源,將一切數據視爲資源是REST區別與其他架構風格的最本質屬性
- 對於REST這種面向資源的架構風格,有人提出一種全新的結構理念,即:面向資源架構(ROA:Resource Oriented Architecture)
二、 RESTful - 10條規範
2-1 API與用戶的通信協議,總是使用HTTPs協議
HTTPs = HTTP + SSL ,部署需要去域名站點申請SSL證書
2-2 API部署的兩種規範
2-2-1 方式一、將API部署在本站域名內部 - 不推薦,存在跨域問題
# https://api.example.com 例如寫一個查詢所有圖書的api接口 - https://api.example.com/books
2-2-2 方式二、將API部署在域名末尾 - 推薦,使用簡單
# https://example.org/api/ 例如寫一個查詢所有圖書的api接口:https://127.0.0.1/api/books
2-3 API在路徑上的書寫原則 - 面向資源
'''視網絡上任何東西都是資源,均使用名詞表示(可複數)''' # 例如: https://api.example.com/v1/books 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 # 統一都books名詞: https://api.example.com/v1/books
2-4 API的版本部署規則(兩種方式)
2-4-1 方式一、部署在url上(兩種方式)
# 方式一 https://api.example.com/v1/books # 方式二(推薦) https://example.org/api/v1/books
2-4-2 方式二、放在請求頭內(不推薦,跨域時會引發多次請求)
2-5 RESTful規範支持方法
GET 從服務器取出資源(一項或多項) POST 在服務器新建一個資源 - 非冪等 PUT 在服務器更新資源(客戶端提供改變後的完整資源,即獲取對象所在的所有資源內容) - 冪等 PATCH 在服務器更新資源(客戶端提供改變的屬性,即只獲取改變的對象) DELETE 從服務器刪除資源 2-5-1 冪等性 - 對接口的多次調用所產生的結果和調用一次是一致的
例:put請求是冪等的,post請求不是冪等的
2-6 過濾方式規範 - 通過在url上傳參的形式傳遞搜索條件
# 指定返回記錄的數量 https://api.example.com/v1/zoos?limit=10 # 指定返回記錄的開始位置 https://api.example.com/v1/zoos?offset=10 # 指定第幾頁,以及每頁的記錄數 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
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 - [*]:服務器發生錯誤,用戶將無法判斷髮出的請求是否成功。
2-8 錯誤信息的返回 - key-value形式
{status:100,error:'錯誤信息'}
2-9 不同路由方法申請,對相同路由的不同結果返回
GET /books:返回資源對象的列表(數組) GET /books/1:返回單個資源對象 POST /books:新建資源對象,返回新生成的資源對象 PUT /books/1:更新單個對象資源,返回完整的資源對象 PATCH /books/1:更新單個對象資源,返回完整的資源對象 DELETE /books/1:刪除單個對象資源,返回一個空文檔
2-10 Hypermedia API - 返回結果中提供指向其他API的鏈接
{ status:100 msg:成功 url:127.0.0.1/books/1 }
三、Django實現RESTful規範操作
注意:
- Django存在侷限性,只封裝了POST和GET方法,對於其他方法需要自行封裝操作(對body進行處理)
3-1 基於FBV的實現方式
def user(request): if request.method=='GET': dic = {'status':200,'name': 'name', 'age': 18} return HttpResponse(json.dumps(dic)) elif request.method=='POST': # 狀態碼的返回,及信息返回 dic = {'status': 200, 'msg': '修改成功','url':'127.0.0.1/users/1'} return JsonResponse(dic)
3-2 基於CBV的實現方式
from django.shortcuts import render, HttpResponse from django.views import View class Test(View): # dispatch用於請求的分發,若重寫則覆蓋,必須調用父類的原生方法 def dispatch(self, request, *args, **kwargs): print(11) return super().dispatch(request, *args, **kwargs) # 如果發送一個get 請求,會響應到這個函數 # request必須傳,後面的可傳可不傳(有可能有名,無名分組) def get(self, request, *args, **kwargs): print('get') return render(request, 'login.html') def post(self, request): name = request.POST.get('name') pwd = request.POST.get('pwd') if name == 'lqz' and pwd == '123': return HttpResponse('登錄成功') else: return render(request, 'login.html', {'error': '用戶名或密碼錯誤'})
3-3 基於CBV對RESTful規範方法的實現
''' 路由設計 url(r'^books/$', views.Books.as_view()), url(r'^books/(?P<pk>\d+)', views.Books.as_view()), ''' from app01 import models # 基於CBV模擬resful規範的接口 - get、put、post class Books(View): # 獲取所有圖書 def get(self, request): print(type(request)) response = {'status': 100, 'data': None} books = models.Book.objects.all() # 先構造出所有書籍的字典的列表 ll = [{'name': book.name, 'price': book.price} for book in books] # 返回數據是json格式數據 response['data'] = ll return JsonResponse(response, safe=False) # 數據的修改 - Django內部未支持,自主對傳輸的數據進行反序列化處理 def put(self, request, pk): import json data=json.loads(str(request.body,encoding='utf-8')) name=data.get('name') price=data.get('price') ret = models.Book.objects.filter(pk=pk).update(name=name,price=price) print(ret) return JsonResponse({'status': 100, 'msg': '修改成功'}) # 數據的查詢 def post(self, request, pk): print(pk) print(request.method) print(request.body) print(request.POST) print(request.GET) name = request.POST.get('name') price = request.POST.get('price') print(name) ret = models.Book.objects.filter(pk=pk).update(name=name,price=price) print(ret) return JsonResponse({'status': 100, 'msg': '修改成功'})
3-3-1 使用Postman 跳過前端模擬請求獲取數據
3-3-2 使用Postman的報錯信息總結
解決方式:使用Django的後臺傳輸,不支持CSRF傳輸,需要註釋(不安全)