DjangoRestFramework,restful規範、APIview、解析器組件、Postman等
- 2019 年 12 月 20 日
- 筆記
一 預備知識
預備知識:django的CBV和FBV
CBV(class based view):多用,簡單回顧一下
FBV(function based view):
CBV模式的簡單操作:來個登陸頁面吧
login.html文件內容如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="{% url 'login' %}" method="post"> {% csrf_token %} 用戶名: <input type="text" name="username"> 密碼: <input type="text" name="password"> <input type="submit"> </form> </body> </html>url.py內容如下
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.LoginView.as_view(),name='login'), ]
views.py
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from django.views import View class LoginView(View): def get(self,request): return render(request,'login.html') def post(self,request): return HttpResponse('post')大家還記得CBV的這個視圖函數,為什麼get請求就能找到類的get方法,post請求就能找到post方法,其內部有個dispatch方法來進行分發,這又怎麼玩呢,看源碼啦,從哪裡看呢?那裡先執行,就從哪裡看
views.LoginView.as_view()這個東西是不是先執行啊,url接收到請求,調用了它對不對,as_view()類方法,這個類方法給你返回了一個叫view的方法,就是說這個url對應這個一個view方法,當用戶訪問login頁面的時候是不是就是執行了view(request),大家進去看看源碼吧。
然後你就可以玩dispatch方法了,看程式碼:
from django.shortcuts import render,HttpResponse,redirect # Create your views here. from django.views import View class LoginView(View): def dispatch(self, request, *args, **kwargs): print('something...') res = super().dispatch(request, *args, **kwargs) #注意,不用傳self,為什麼呢,因為super已經幫你吧self放進去啦 print('someting....') return res def get(self,request): return render(request,'login.html') def post(self,request): return HttpResponse('post')為什麼要說它呢,因為後面咱們的drf學習,就要用它啦。
二 restful規範
摘自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html
1. 什麼是RESTFUl
RESTful 是目前最流行的 API 設計規範,用於 Web 數據介面的設計。
REST與技術無關,代表的是一種軟體架構風格,REST是Representational State Transfer的簡稱,中文翻譯為「表徵狀態轉移」
REST從資源的角度類審視整個網路,它將分布在網路中某個節點的資源通過URL進行標識,客戶端應用通過URL來獲取資源的表徵,獲得這些表徵致使這些應用轉變狀態
所有的數據,不過是通過網路獲取的還是操作(增刪改查)的數據,都是資源,將一切數據視為資源是REST區別與其他架構風格的最本質屬性
對於REST這種面向資源的架構風格,有人提出一種全新的結構理念,即:面向資源架構(ROA:Resource Oriented Architecture)
另外還有其他兩種,簡單了解。
遠程過程調用(RPC) 遠程過程調用為 Web 服務提供一個分散式函數/方法介面供用戶調用。這是一種較傳統的方式。通常,在 WSDL 中對 RPC 介面進行定義(類似於早期的XML-RPC)。本質上,RPC 方式利用一個簡單映射,把用戶請求直接轉化成一個特定語言編寫的函數/方法。現在,該方式已不再使用。 面向服務架構(SOA) 面向服務架構現在,業界比較關注的是遵從面向服務架構(Service-oriented architecture,SOA)來構建 Web 服務。該方式中,通訊是由消息驅動,而不再是某個動作(方法調用)。這種 Web 服務也稱為「面向消息的服務」。
網路應用程式,分為前端和後端兩個部分。當前的發展趨勢,就是前端設備層出不窮(手機、平板、桌面電腦、其他專用設備......)。
因此,必須有一種統一的機制,方便不同的前端設備與後端進行通訊。這導致API構架的流行,甚至出現"API First"的設計思想。RESTful API是目前比較成熟的一套互聯網應用程式的API設計理論。還有一篇《理解RESTful架構》,探討如何理解這個概念。
表徵狀態轉移大概圖解:

2.RESTFUl API設計
2.1 使用協議
API與用戶的通訊協議,總是使用HTTPs協議。
2.2 使用域名
應該盡量將API部署在專用域名之下,意思就是給API專門做一個伺服器。
https://api.example.com
如果確定API很簡單,不會有進一步擴展,可以考慮放在主域名下。
https://example.org/api/
2.3 版本提示
網站的API可能一直在更新,那麼應該將API的版本號放入URL。
https://api.example.com/v1/
另一種做法是,將版本號放在HTTP頭資訊中,但不如放入URL方便和直觀。Github採用這種做法。
2.4 路徑寫法
路徑又稱"終點"(endpoint),表示API的具體網址。
在RESTful架構中,每個網址代表一種資源(resource),所以網址中不能有動詞,只能有名詞,而且所用的名詞往往與資料庫的表格名對應。一般來說,資料庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應該使用複數。
舉例來說,有一個API提供動物園(zoo)的資訊,還包括各種動物和僱員的資訊,則它的路徑應該設計成下面這樣。
https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employees
2.5 HTTP動詞
對於資源的具體操作類型,由HTTP動詞表示,請求方式時動詞,我們後端基於請求方式來分發對應的視圖函數來進行邏輯處理和數據處理、提取、加工等操作,但是URL中不能出現動詞。
常用的HTTP動詞有下面五個(括弧里是對應的SQL命令)。
GET(SELECT):從伺服器取出資源(一項或多項)。 POST(CREATE):在伺服器新建一個資源。 PUT(UPDATE):在伺服器更新資源(客戶端提供改變後的完整資源)。 PATCH(UPDATE):在伺服器更新資源(客戶端提供改變的屬性,更新部分資源的意思)。他和put用哪個都可以,沒有太大的區別,我們用put方式偏多 DELETE(DELETE):從伺服器刪除資源。
還有兩個不常用的HTTP動詞。
HEAD:獲取資源的元數據。 OPTIONS:獲取資訊,關於資源的哪些屬性是客戶端可以改變的
下面是一些例子。RESTful 的核心思想就是,客戶端發出的數據操作指令都是"動詞 + 賓語"的結構。比如,GET /articles這個命令,GET是動詞,/articles是賓語。根據 HTTP 規範,動詞一律大寫。
GET /zoos:列出所有動物園 POST /zoos:新建一個動物園 GET /zoos/ID:獲取某個指定動物園的資訊 PUT /zoos/ID:更新某個指定動物園的資訊(提供該動物園的全部資訊) PATCH /zoos/ID:更新某個指定動物園的資訊(提供該動物園的部分資訊) DELETE /zoos/ID:刪除某個動物園 GET /zoos/ID/animals:列出某個指定動物園的所有動物 DELETE /zoos/ID/animals/ID:刪除某個指定動物園的指定動物
動詞覆蓋:
有些客戶端只能使用GET和POST這兩種方法。伺服器必須接受POST模擬其他三個方法(PUT、PATCH、DELETE)。
這時,客戶端發出的 HTTP 請求,要加上X-HTTP-Method-Override屬性,告訴伺服器應該使用哪一個動詞,覆蓋POST方法。
POST /api/Person/4 HTTP/1.1 X-HTTP-Method-Override: PUT
上面程式碼中,X-HTTP-Method-Override指定本次請求的方法是PUT,而不是POST。
賓語必須是名字:
賓語就是 API 的 URL,是 HTTP 動詞作用的對象。它應該是名詞,不能是動詞。比如,/articles這個 URL 就是正確的,而下面的 URL 不是名詞,所以都是錯誤的。
/getAllCars /createNewCar /deleteAllRedCars
既然 URL 是名詞,那麼應該使用複數,還是單數?
這沒有統一的規定,但是常見的操作是讀取一個集合,比如GET /articles(讀取所有文章),這裡明顯應該是複數。
為了統一起見,建議都使用複數 URL,比如GET /articles/2要好於GET /article/2。

2.6 過濾資訊(filtering,或稱查詢參數)
如果記錄數量很多,伺服器不可能都將它們返回給用戶。API應該提供參數,過濾返回結果。
下面是一些常見的參數。
?limit=10:指定返回記錄的數量 ?offset=10:指定返回記錄的開始位置。 ?page=2&per_page=100:指定第幾頁,以及每頁的記錄數。 ?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序。 ?animal_type_id=1:指定篩選條件
參數的設計允許存在冗餘,即允許API路徑和URL參數偶爾有重複。比如,GET /zoo/ID/animals 與 GET /animals?zoo_id=ID 的含義是相同的。
常見的情況是,資源需要多級分類,因此很容易寫出多級的 URL,比如獲取某個作者的某一類文章。
GET /authors/12/categories/2
這種 URL 不利於擴展,語義也不明確,往往要想一會,才能明白含義。
更好的做法是,除了第一級,其他級別都用查詢字元串表達。
GET /authors/12?categories=2
下面是另一個例子,查詢已發布的文章。你可能會設計成下面的 URL。
GET /articles/published
查詢字元串的寫法明顯更好
GET /articles?published=true
2.7 狀態碼
2.7.1 狀態碼必須精確
客戶端的每一次請求,伺服器都必須給出回應。回應包括 HTTP 狀態碼和數據兩部分。
HTTP 狀態碼就是一個三位數,分成五個類別。
1xx:相關資訊 2xx:操作成功 3xx:重定向 4xx:客戶端錯誤 5xx:伺服器錯誤
這五大類總共包含100多種狀態碼,覆蓋了絕大部分可能遇到的情況。每一種狀態碼都有標準的(或者約定的)解釋,客戶端只需查看狀態碼,就可以判斷出發生了什麼情況,所以伺服器應該返回儘可能精確的狀態碼。
API 不需要1xx狀態碼,下面介紹其他四類狀態碼的精確含義。
2.7.2 2xx狀態碼
200狀態碼錶示操作成功,但是不同的方法可以返回更精確的狀態碼。
GET: 200 OK POST: 201 Created PUT: 200 OK PATCH: 200 OK DELETE: 204 No Content
上面程式碼中,POST返回201狀態碼,表示生成了新的資源;DELETE返回204狀態碼,表示資源已經不存在。
此外,202 Accepted狀態碼錶示伺服器已經收到請求,但還未進行處理,會在未來再處理,通常用於非同步操作。下面是一個例子。
HTTP/1.1 202 Accepted { "task": { "href": "/api/company/job-management/jobs/2130040", "id": "2130040" } }2.7.3 3xx狀態碼
API 用不到301狀態碼(永久重定向)和302狀態碼(暫時重定向,307也是這個含義),因為它們可以由應用級別返回,瀏覽器會直接跳轉,API 級別可以不考慮這兩種情況。
API 用到的3xx狀態碼,主要是303 See Other,表示參考另一個 URL。它與302和307的含義一樣,也是"暫時重定向",區別在於302和307用於GET請求,而303用於POST、PUT和DELETE請求。收到303以後,瀏覽器不會自動跳轉,而會讓用戶自己決定下一步怎麼辦。下面是一個例子。
HTTP/1.1 303 See Other Location: /api/orders/12345
2.7.4 4xx狀態碼
4xx狀態碼錶示客戶端錯誤,主要有下面幾種。
400 Bad Request:伺服器不理解客戶端的請求,未做任何處理。 401 Unauthorized:用戶未提供身份驗證憑據,或者沒有通過身份驗證。 403 Forbidden:用戶通過了身份驗證,但是不具有訪問資源所需的許可權。 404 Not Found:所請求的資源不存在,或不可用。 405 Method Not Allowed:用戶已經通過身份驗證,但是所用的 HTTP 方法不在他的許可權之內。 410 Gone:所請求的資源已從這個地址轉移,不再可用。 415 Unsupported Media Type:客戶端要求的返回格式不支援。比如,API 只能返回 JSON 格式,但是客戶端要求返回 XML 格式。 422 Unprocessable Entity :客戶端上傳的附件無法處理,導致請求失敗。 429 Too Many Requests:客戶端的請求次數超過限額。
2.7.5 5xx狀態碼
5xx狀態碼錶示服務端錯誤。一般來說,API 不會向用戶透露伺服器的詳細資訊,所以只要兩個狀態碼就夠了。
500 Internal Server Error:客戶端請求有效,伺服器處理時發生了意外。 503 Service Unavailable:伺服器無法處理請求,一般用於網站維護狀態。
總結一下常用狀態碼及對應的描述
200 OK - [GET]:伺服器成功返回用戶請求的數據,該操作是冪等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。 202 Accepted - [*]:表示一個請求已經進入後台排隊(非同步任務) 204 NO CONTENT - [DELETE]:用戶刪除數據成功。301 狀態碼(永久重定向)302 狀態碼(暫時重定向,307也是這個含義) 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 - [*]:伺服器發生錯誤,用戶將無法判斷發出的請求是否成功。 更多看這裡:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
2.8 伺服器響應
2.8.1 響應數據格式
API 返回的數據格式,不應該是純文本,而應該是一個 JSON 對象,因為這樣才能返回標準的結構化數據。所以,伺服器回應的 HTTP 頭的Content-Type屬性要設為application/json。
客戶端請求時,也要明確告訴伺服器,可以接受 JSON 格式,即請求的 HTTP 頭的ACCEPT屬性也要設成application/json。下面是一個例子。
GET /orders/2 HTTP/1.1 Accept: application/json
2.8.2 發生錯誤時的響應
發生錯誤時不要響應200狀態碼,有一種不恰當的做法是,即使發生錯誤,也返回200狀態碼,把錯誤資訊放在數據體裡面,就像下面這樣。
HTTP/1.1 200 OK Content-Type: application/json { "status": "failure", "data": { "error": "Expected at least two items in list." } }上面程式碼中,解析數據體以後,才能得知操作失敗。
這張做法實際上取消了狀態碼,這是完全不可取的。正確的做法是,狀態碼反映發生的錯誤,具體的錯誤資訊放在數據體裡面返回。下面是一個例子。
HTTP/1.1 400 Bad Request Content-Type: application/json { "error": "Invalid payoad.", "detail": { "surname": "This field is required." } }2.8.3 響應結果
針對不同操作,伺服器向用戶返回的結果應該符合以下規範。
GET /collection:返回資源對象的列表(數組),一般是[{"id":1,"name":"a",},{"id":2,name:"b"},]這種類型 GET /collection/resource:返回單個資源對象, 一般是查看的單條數據 {"id":1,"name":'a'} POST /collection:返回新生成的資源對象 , 一般是返回新添加的數據資訊, 格式一般是{} PUT /collection/resource:返回完整的資源對象 一般時返回更新後的數據,{} PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔 一般返回一個空字元串例如:

2.9 Hypermedia API,提供鏈接
RESTful API最好做到Hypermedia,即返回結果中提供鏈接,API 的使用者未必知道,URL 是怎麼設計的。一個解決方法就是,在回應中,給出相關鏈接,便於下一步操作。這樣的話,用戶只要記住一個 URL,就可以發現其他的 URL。這種方法叫做 HATEOAS。
舉例來說,GitHub 的 API 都在 api.github.com 這個域名。訪問它,就可以得到其他 URL。
{ ... "feeds_url": "https://api.github.com/feeds", "followers_url": "https://api.github.com/user/followers", "following_url": "https://api.github.com/user/following{/target}", "gists_url": "https://api.github.com/gists{/gist_id}", "hub_url": "https://api.github.com/hub", ... }上面的回應中,挑一個 URL 訪問,又可以得到別的 URL。對於用戶來說,不需要記住 URL 設計,只要從 api.github.com 一步步查找就可以了。
HATEOAS 的格式沒有統一規定,上面例子中,GitHub 將它們與其他屬性放在一起。更好的做法應該是,將相關鏈接與其他屬性分開。
HTTP/1.1 200 OK Content-Type: application/json { "status": "In progress", "links": {[ { "rel":"cancel", "method": "delete", "href":"/api/status/12345" } , { "rel":"edit", "method": "put", "href":"/api/status/12345" } ]} }再比如:當用戶向api.example.com的根目錄發出請求,會得到這樣一個文檔。
{"link": { "rel": "collection https://www.example.com/zoos", "href": "https://api.example.com/zoos", "title": "List of zoos", "type": "application/vnd.yourformat+json" }}上面程式碼表示,文檔中有一個links屬性,用戶讀取這個屬性就知道下一步該調用什麼API了。rel表示這個API與當前網址的關係(collection關係,並給出該collection的網址),href表示API的路徑,title表示API的標題,type表示返回類型。
2.10 其他
(1)API的身份認證應該使用OAuth 2.0框架。
(2)伺服器返回的數據格式,應該盡量使用JSON,避免使用XML。
三 Django RestFramework(簡稱DRF)
drf是django發展來的一個符合restful介面規範的一個東西,啥東西呢,就是django的一個app,還記得app是啥不。DRF官網地址,但是大家記住一句話,即便是沒有這drf,我們照樣能做前後端分離的項目,自己做規範的數據介面,返回json數據,都是沒問題的昂,那為什麼還用drf啊,這個更nb。
在官網中我們看一下這裡:

首先下載安裝,django是必須要的,不過咱們的django已經下載好了,如果沒下載好,那麼pip install django,執行一下:
pip install django pip install djangorestframework //執行這句話,下載drf # Set up a new project with a single application django-admin startproject tutorial . # Note the trailing '.' character cd tutorial django-admin startapp quickstart cd ..
1.先基於djangoCBV,不用DRF來寫個介面,看看效果
好,接下來我們創建一個django項目,models中創建一個表,添加一些數據,然後寫一個數據介面來獲取一下這些數據,返回json數據類型,按照我們CBV的模式來寫,但是下面還沒有用到我們的drf昂,只是告訴大家,沒有drf,你也能做。


views.py文件內容如下:
from django.shortcuts import render,HttpResponse,redirect import json # Create your views here. from django.views import View from app01 import models class CourseView(View): def get(self,request): #拿到queryset類型的數據,要加工成[{},{}]這種數據類型 course_obj_list = models.Course.objects.all() ret = [] for course_obj in course_obj_list: ret.append({ "title":course_obj.title, "desc":course_obj.desc, }) return HttpResponse(json.dumps(ret,ensure_ascii=False)) #ensure_ascii=False是告訴json不要對中文進行編碼,不然返回給前端的數據中如果有中文的話會被編碼成unicode類型的數據,導致前端看不到中文urls.py內容如下:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ #url(r'^admin/', admin.site.urls), url(r'^courses/', views.CourseView.as_view(),name='courses'), #介面就寫好啦 ]
然後啟動項目,在瀏覽器中一訪問,就看到了我們後端返回的json數據:

有人就又說了,我們這麼寫也ok啊,要drf幹嘛,上面這個例子是個簡單的例子,數據簡單、邏輯簡單,你這樣寫當然看著沒有問題啦,但是數據量很大,結構很複雜的時候,你這樣寫的時候就頭疼了。
所以上面這個例子你就作為了解吧,我們玩一下drf。
玩DRF之前,我們先說一下我們DRF中有哪些內容:
咱們玩下面10個組件: a.APIView (*****) b.序列化組件 (*****) c.試圖類(mixin) (*****) d.認證組件 (*****) e.許可權組件 f.頻率組件 g.分頁組件 h.解析器組件 (*****) i.相應其組件 j.url控制器
2.基於DRF來寫介面
2.1 APIView組件
在我們的視圖中,通過CBV來寫視圖的時候,繼承APIView,url不變,還是上面那個,通過瀏覽器訪問,照樣能夠看到我們返回的數據,
views.py內容如下:
from django.shortcuts import render,HttpResponse,redirect import json from django.views import View from app01 import models #引入APIView,APIView是繼承的django的View,也就是APIView在View的基礎上添加了一些其他的功能 from rest_framework.views import APIView class CourseView(APIView): def get(self,request): course_obj_list = models.Course.objects.all() ret = [] for course_obj in course_obj_list: ret.append({ "title":course_obj.title, "desc":course_obj.desc, }) return HttpResponse(json.dumps(ret, ensure_ascii=False))urls.py內容如下:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^courses/', views.CourseView.as_view(),name='courses'), ]
頁面訪問url效果:

照樣拿到了數據,那麼怎麼回事兒呢,我們看源碼,知道一下APIView的流程就行。
2.2 解析器組件
知識準備,還記得一個叫做contentType的http請求頭的東西嗎?回想一下。

後端根據contentType的類型來找到對應的解析數據的方法來解析數據,提取數據

但是django沒有內置的自動解開json數據類型的方法,那麼只能去request.body裡面拿原始的bytes類型的數據,然後自己解,其實很簡單,但是django沒有,可能是早先沒有考慮到。

django自動通過contentType來解析數據的那些方法就叫做django的解析器,能解的是urlencode和文件的那個mutipart/form-data類型的數據,然後將數據放到了request.POST方法裡面。
def post(self,request): print(request.POST) print(type(request)) #通過這個對象的類型(類對象),找到它的源碼看看 return HttpResponse('POST')而DRF通過自己的解析器,幫我們給request裡面封裝了一個request.data屬性,獲取請求體裡面的數據,然後解析,並且這個解析器基本上能夠解析所有的數據類型,包括django不能自動解析的json數據類型,我們通過Postman(關於Postman工具的使用,看下面那個章節)來調試一下,看看效果

def post(self,request): print(request.data) #列印結果是:{'name': 'chao'} return HttpResponse('POST')我們接著往下看:首先我們給我們的試圖類添加一個類變數,這些類變數是用來控制我們視圖類裡面的各個組件

看一下程式碼:
from django.shortcuts import render,HttpResponse,redirect import json from django.views import View from app01 import models from rest_framework.views import APIView #導入解析器 from rest_framework.parsers import JSONParser,FormParser,MulTiPartParser # JSONParser:解析json數據的額 # FormParser:解析urlencoded數據的 # FileUploadParser:解析文件數據的 class CourseView(APIView): #寫一個類屬性,名字必須是parser_classes parser_classes = [JSONParser,] #裡面存放我們上面導入的那幾個解析器,如果我們裡面寫了一個JSONParser,那麼解析器只能解析前端發送過來的json數據,存放到request.data裡面,可以通過postman測試一下看看效果,為什麼?看源碼吧 def get(self,request): course_obj_list = models.Course.objects.all() ret = [] for course_obj in course_obj_list: ret.append({ "title":course_obj.title, "desc":course_obj.desc, }) return HttpResponse(json.dumps(ret, ensure_ascii=False)) def post(self,request): print('ok') #你會發現,即便是發送的數據類型不對,post方法也走了,但是request.data沒有東西,那麼肯定是它出了問題 print(request.data) #request.data對我們的數據進行解析的,那麼說明data不是一個變數,而是一個屬性方法,還記得屬性方法嗎 return HttpResponse('POST')源碼看著比較複雜,這裡我就不列舉了,反正你要知道的是,我們的解析器的查找使用順序是:
自己寫的類裡面的parser_classes = [JSONParser,]---->然後找settings中的----->然後找默認的,只要找到,就用了。其他的組件也都是這麼個順序,所以其他的咱們就不看了。
四 Postman的使用
Postman是一個模擬發送請求並獲得響應結果的工具,不用這個工具的時候,我們寫web項目,調試介面返回數據的時候,是不是都要啟動項目,通過瀏覽器訪問,然後查看數據啊,有了這個工具我們就可以不用啟動瀏覽器來,通過這個工具就能進行調試,首先下載安裝
下載地址:https://www.getpostman.com/downloads/
安裝,然後使用,直接看圖吧,一看就明白:


