Python自动化开发 - RESTful API
本節內容
1. ?RESTful 簡介
2. ?RESTful 設計指南
3. ?Django REST Framework 最佳實踐
4. ?理論拓展與開放平臺
5. ?API文檔化與測試
?
| 一 ?RESTful 簡介 |
?
?
傳統理解,軟件和網絡是兩個不同的領域,很少有交集:軟件開發主要針對單機環境,網絡則主要研究系統之間的通信
互聯網的興起,使得兩個領域開始融合,現在我們必須考慮,如何開發在互聯網環境中使用的軟件
網站即軟件,這種“互聯網軟件”采用客戶端/服務器模式,建立在分布式體系上,通過互聯網通信,具有高延時、高并發等特點
RESTful架構,就是目前最流行的一種互聯網軟件架構
1. 起源
REST這個詞,是Roy Thomas Fielding在他2000年的博士論文中提出的
Fielding 一個非常重要的人物,HTTP協議(1.0版和1.1版)的主要設計者、Apache服務器軟件的作者之一、Apache基金會的第一認主席
2. 名稱
REST,Representational State Transfer,即“表現層狀態轉化”,如果一個架構符合REST原則,就稱為RESTful架構
3. 資源(Resources)
REST的名稱"表現層狀態轉化"中,省略了主語。"表現層"其實指的是"資源"(Resources)的"表現層"
所謂"資源",就是網絡上的一個實體,或者說是網絡上的一個具體信息。它可以是一段文本、一張圖片、一首歌曲、一種服務,總之就是
一個具體的實在。你可以用一個URI(統一資源定位符)指向它,每種資源對應一個特定的URI。要獲取這個資源,訪問它的URI就可以,
因此URI就成了每一個資源的地址或獨一無二的識別符。
所謂"上網",就是與互聯網上一系列的"資源"互動,調用它的URI
4. 表現層(Representaion)
"資源"是一種信息實體,它可以有多種外在表現形式。我們把"資源"具體呈現出來的形式,叫做它的"表現層"(Representation)。
比如,文本可以用txt格式表現,也可以用HTML格式、XML格式、JSON格式表現,甚至可以采用二進制格式;圖片可以用JPG格式表現,
也可以用PNG格式表現。
URI只代表資源的實體,不代表它的形式。嚴格地說,有些網址最后的".html"后綴名是不必要的,因為這個后綴名表示格式,屬于
"表現層"范疇,而URI應該只代表"資源"的位置。它的具體表現形式,應該在HTTP請求的頭信息中用Accept和Content-Type字段指定,
這兩個字段才是對"表現層"的描述。
5. 狀態轉化(State Transfer)
訪問一個網站,就代表了客戶端和服務器的一個互動過程。在這個過程中,勢必涉及到數據和狀態的變化
互聯網通信協議HTTP協議,是一個無狀態協議。這意味著,所有的狀態都保存在服務器端。因此,如果客戶端想要操作服務器,
必須通過某種手段,讓服務器端發生“狀態轉化”(State Transfer),而這種轉化是建立在表現層之上的,所以就是“表現層狀態轉化”
客戶端用到的手段,只能是HTTP協議。具體來說,就是HTTP協議里面,四個表示操作方式的動詞:GET、POST、PUT、DELETE。
它們分別對應四種基本操作:GET用來獲取資源,POST用來新建資源(也可以用于更新資源),PUT用來更新資源,DELETE用來刪除資源
6. 綜述
綜合上面的解釋,我們總結一下什么是RESTful架構:
(1)每一個URI代表一種資源;
(2)客戶端和服務器之間,傳遞這種資源的某種表現層;
(3)客戶端通過四個HTTP動詞,對服務器端資源進行操作,實現"表現層狀態轉化"。
7. 設計誤區
最常見的一種設計錯誤,就是URI包含動詞。因為"資源"表示一種實體,所以應該是名詞,URI不應該有動詞,動詞應該放在HTTP協議中
舉例來說,某個URI是/posts/show/1,其中show是動詞,這個URI就設計錯了,正確的寫法應該是/posts/1,然后用GET方法表示show
如果某些動作是HTTP動詞表示不了的,你就應該把動作做成一種資源。比如網上匯款,從賬戶1向賬戶2匯款500元,錯誤的URI是:
POST /accounts/1/transfer/500/to/2正確的寫法是把動詞transfer改成名詞transaction,資源不能是動詞,但是可以是一種服務:
POST /transaction HTTP/1.1 Host: 127.0.0.1from=1&to=2&amount=500.00?
| 二 ?RESTful API 設計指南 |
?
?
接下來介紹RESTful API 的設計細節,探討如何設計一套合理、好用的API
1. 協議
API與用戶的通信協議, 總是 使用https協議
2. 域名
應該盡量將API部署在專用域名之下
https://api.example.com如果確定API很簡單,不會有進一步擴展,可以考慮放在主域名下
https://example.org/api/3. 版本(Versioning)
可以將API的版本號放入URL
https://api.example.com/v1/另一種做法是,將版本號放在HTTP頭信息中,但不如放入URL方便和直觀。Github采用這種做法
4. 路徑(Endpoint)
路徑又稱“終點”(endpoint),表示API的具體網址
在RESTful架構中,每個網址代表一種資源(resource),所以網址中不能有動詞,只能有名詞,而且所用的名詞往往與數據庫的表格名對應
一般來說,數據庫中的表都是同種記錄的"集合"(collection),所以API中的名詞也應該使用復數。
https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employees5. HTTP動詞
對于資源的具體操作類型,由HTTP動詞表示
常用的HTTP動詞有下面五個(括號里是對應的SQL命令)
GET(SELECT):從服務器取出資源(一項或多項)。 POST(CREATE):在服務器新建一個資源。 PUT(UPDATE):在服務器更新資源(客戶端提供改變后的完整資源)。 PATCH(UPDATE):在服務器更新資源(客戶端提供改變的屬性)。 DELETE(DELETE):從服務器刪除資源。還有兩個不常用的HTTP動詞
HEAD:獲取資源的元數據。 OPTIONS:獲取信息,關于資源的哪些屬性是客戶端可以改變的。下面是一些例子
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:刪除某個指定動物園的指定動物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 的含義是相同的
7. 狀態碼(Status Codes)
服務器向用戶返回的狀態碼和提示信息,常見的有以下一些(方括號中是該狀態碼對應的HTTP動詞)
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 - [*]:服務器發生錯誤,用戶將無法判斷發出的請求是否成功。狀態碼的完全列表參見這里
8. 錯誤處理(Error Handling)
?如果狀態碼是4xx,就應該向用戶返回出錯信息。一般來說,返回的信息中將error作為鍵名,出錯信息作為鍵值即可
{error: "Invalid API key" }9. 返回結果
針對不同操作,服務器向用戶返回的結果應該符合以下規范
GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔10. ?Hypermedia API
RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什么
比如,當用戶向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" }}上面代碼表示,文檔中有一個link屬性,用戶讀取這個屬性就知道下一步該調用什么API了
rel表示這個API與當前網址的關系(collection關系,并給出該collection的網址)
href表示API的路徑,
title表示API的標題,
type表示返回類型
Hypermedia API的設計被稱為HATEOAS。Github的API就是這種設計,訪問api.github.com會得到一個所有可用API的網址列表
{"current_user_url": "https://api.github.com/user","authorizations_url": "https://api.github.com/authorizations",// ... }從上面可以看到,如果想獲取當前用戶的信息,應該去訪問api.github.com/user,然后就得到了下面結果
{"message": "Requires authentication","documentation_url": "https://developer.github.com/v3" }上面代碼表示,服務器給出了提示信息,以及文檔的網址
11.其他
API的身份認證應該使用OAuth 2.0框架
服務器返回的數據格式,應該盡量使用JSON,避免使用XML。
?
| 三 ?Django REST Framework 最佳實踐 |
?
?
注意:這是版本v.3+的REST framework文檔
Django REST framework 是一個強大且靈活的工具包,用以構建Web APIs。?
為什么要使用REST framework??
-?在線可視的API,對于贏得你的開發者們十分有用?
-?驗證策略涵蓋了OAuth1a和OAuth2?
-?同時支持ORM和非ORM數據源的序列化?
-?可以配置各個環節,若無需更多強大的特性,使用一般基于方法(function-based)的視圖(views)即可
-?大量的文檔,強力的社區支持?
-?大公司如同Mozilla和Eventbrite,也是忠實的使用者
?1. ?配置要求
REST framework 有以下的要求:
- Python (2.7, 3.2, 3.3, 3.4, 3.5, 3.6)
- Django (1.7+, 1.8, 1.9, 1.11)
下面是可選的包:
- Markdown (2.1.0+) - Markdown為可視化 API 提供了支持.
- django-filter (0.9.2+) - 過濾支持.
- django-crispy-forms - 為過濾,提供了改良的HTML呈現.
- django-guardian (1.1.1+) - 對象層面的權限支持.
?2. ?安裝部署
使用pip安裝框架及所有的你需要的可選依賴包
pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com djangorestframework pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com markdown pip install -i https://pypi.doubanio.com/simple/ --trusted-host pypi.doubanio.com django-filter…又或者從github上clone該項目
git clone git@github.com:tomchristie/django-rest-framework.git將?'rest_framework'?添加到你的?'INSTALLED_APPS'?設置里
INSTALLED_APPS = (...'rest_framework', )如果你需要使用可視化的API,你也許就需要添加REST Framework的登陸/登出視圖。在項目的?urls.py文件里,添加下面的內容:
urlpatterns = [...url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]3. ?示例
讓我們看一個簡單用例:如何用REST framework 來搭建一個簡單的支持modle的API?
我們將創建一個讀/寫API,來處理我們項目中的用戶信息。?
任何REST framework的全局設置,都存放在一個配置字典(dictionary,有些語言如Java中的map)中,名為REST_FRAMEWORK。
我們從以下的操作開始,把下面的內容添加到項目的settings.py模塊中:
REST_FRAMEWORK = {# 使用Django的標準`django.contrib.auth`權限管理類,# 或者為尚未認證的用戶,賦予只讀權限.'DEFAULT_PERMISSION_CLASSES': ['rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'] }這是項目目錄下urls.py模塊:
from django.conf.urls import url, include from django.contrib.auth.models import User from rest_framework import routers, serializers, viewsets# Serializers定義了API的表現. class UserSerializer(serializers.HyperlinkedModelSerializer):class Meta:model = Userfields = ('url', 'username', 'email', 'is_staff')# ViewSets 定義了 視圖(view) 的行為. class UserViewSet(viewsets.ModelViewSet):queryset = User.objects.all()serializer_class = UserSerializer# Routers 提供了一種簡單途徑,自動地配置了URL。 router = routers.DefaultRouter() router.register(r'users', UserViewSet)# 使用自動的URL路由,讓我們的API跑起來。 # 此外,我們也包括了登入可視化API的URLs。 urlpatterns = [url(r'^', include(router.urls)),url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ]啟動項目 python manage runserver 8000 瀏覽器?http://127.0.0.1:8000/里,打開新建的’users’ API了
使用右上角的登陸控制,可以對系統用戶進行新增和刪除操作
?
| 四 理論拓展與開放平臺 |
?
?
1. ?通俗語言解釋REST和RESTful API
URL定位資源,用HTTP動詞(GET,POST,PUT,DELETE)描述操作
-
REST描述的是網絡中clien和server的一種交互形式;REST本身不實用,實用的是如何設計RESTful API(REST風格的網絡接口)
-
Server提供的RESTful API中,URL只使用名詞來指定資源,原則上不使用動詞。“資源”是REST架構或者說整個網絡處理的核心
-
用HTTP協議里的動詞來實現資源的獲取,添加,修改和刪除等操作
-
Server和Client之間傳遞某種資源的一個表現形式。如json、xml傳輸文本,png、jpg傳輸圖片等
-
用HTTP Status Code 傳遞Server的狀態信息
“古代”網頁是前端和后端融在一起,比如PHP,JSP等。在之前的桌面時代問題不大,但移動互聯網的發展,各種類型的Client層出不窮,
RESTful可以通過統一的接口為Web,IOS和Android提供服務。由此可見,Web,iOS,Android和第三方開發者變為平等的角色
通過一套API來共同消費Server提供的服務,前端和后端實現開發分離。
附挺有意思的解釋:
傳統的接口設計,就是過程式的,每個特定的動作有特定的接口。
RESTful,其實就是一個面向對象的接口,接口是對象,這個對象有GET,POST,PUT,DELETE等等成員函數(接口)
?
2. 常見的第三方API開放平臺
https://developer.github.com/v3/
api.jd.com
http://open.weibo.com/wiki/%E5%BE%AE%E5%8D%9AAPI
?
| 五 API文檔化與測試 |
?
?
API開發完畢各種文檔及時整理,包括與產品、前端以及與向部門開放接口說明
1. ?接口文檔
接口描述
簡單描述接口的邏輯和作用
接口地址
正式和測試
請求方法
GET、POST、PUT、DELETE
請求參數
參數名稱 ?類型 描述 ?是否必填 排序 分頁 搜索 ?關聯表處理 批量操作
響應內容
返回的字段名 ?格式json
錯誤代碼
盡量與HTTP保持一致
實例
各種情況的演示實例
開發相關
需求詳細描述、需求流程圖、涉及庫表
2. 測試
測試工具推薦 POSTMAN
?
| 參考與拓展 |
?
?
1. 阮一峰 RESTful API 設計指南
http://www.ruanyifeng.com/blog/2014/05/restful_api.html
2. GitHub 版本示例 ?
https://developer.github.com/v3/media/#request-specific-version
3. HTTP狀態碼匯總
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
4. HATEOAS簡介
https://www.ibm.com/developerworks/cn/java/j-lo-SpringHATEOAS/
5. rest_framework 參考指南
http://www.django-rest-framework.org/
http://blog.csdn.net/ppppfly/article/details/51077433
6.?怎樣用通俗的語言解釋REST以及RESTful
https://www.zhihu.com/question/28557115
轉載于:https://www.cnblogs.com/jonathan1314/p/7154243.html
總結
以上是生活随笔為你收集整理的Python自动化开发 - RESTful API的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 注解的方式实现动态代理基于SpringA
- 下一篇: websocket python爬虫_p