張云飛 楊明光
摘要:隨著網(wǎng)站開發(fā)技術(shù)的發(fā)展,前后端分離的設(shè)計方法已經(jīng)成為主流技術(shù)路線,這種方式一方面能夠使開發(fā)工作精細(xì)化,前后端開發(fā)人員各司其職,互不干擾,另一方面使整個系統(tǒng)易于維護(hù)和擴展。這種開發(fā)模式的關(guān)鍵在于后端開發(fā)人員要設(shè)計出一個簡潔、清晰、權(quán)限分明的通用程序接口,用于與系統(tǒng)前端程序進(jìn)行數(shù)據(jù)交互。本文通過對目前最流行的REST(Representational State Transfer)規(guī)范的研究,實現(xiàn)通用程序接口設(shè)計與開發(fā),進(jìn)而實現(xiàn)應(yīng)用開發(fā)的前后端分離。REST規(guī)范能有效降低開發(fā)人員的溝通成本。Django是采用Python編寫的網(wǎng)絡(luò)程序設(shè)計框架,采用Django框架能極大的簡化通用程序接口設(shè)計的工作量。
關(guān)鍵詞:Django;RESTful;網(wǎng)絡(luò)通用接口
中圖分類號:TP391 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2018)28-0030-03
Research and Practice of RESTful General Program Interface Based on Django
(CNOOC Research Institute, Beijing 100028, China)
Abstract: With the development of Web site development technology, the design method of front and back end separation has become the mainstream technical route, this way can make the development work fine, the front and back end developers have their own duties, mutual interference, on the other hand, the whole system is easy to maintain and expand. The key to this development pattern is that the backend developer should design a concise, clear, and privileged Universal program interface for data interaction with the system front-end program. Through the research of the most popular rest (representational state Transfer) specification, this paper realizes the design and development of universal Program interface, and then realizes the separation of the front and back end of application development. Rest specifications can effectively reduce the communication costs of developers. Django is a network programming framework written in Python, and the Django framework can greatly simplify the work of common Program interface design.
Key words: Django;restful; web API
1 引言
在移動互聯(lián)網(wǎng)時代,各類終端設(shè)備如潮水般涌現(xiàn),如常見的各類PAD,各種尺寸的Mobile,還有已經(jīng)久經(jīng)沙場的各類PC。這些設(shè)備給使用人員帶去了便利,但是對于開發(fā)人員來講卻是噩夢的開始。以往采用瀏覽器的響應(yīng)方式很顯然已經(jīng)無法滿足用戶對高用戶體驗的要求。如何將開發(fā)的應(yīng)用快速適配到各類型設(shè)備,盡可能地減少開發(fā)人員的工作量,提升效率,快速形成生產(chǎn)力,是對開發(fā)人員提成的最迫切的要求。基于此,前后端分離的需求越來越被重視,前端與用戶打交道,負(fù)責(zé)展現(xiàn)數(shù)據(jù)與用戶交互;后端負(fù)責(zé)業(yè)務(wù)和相關(guān)數(shù)據(jù)的處理,前后端通過統(tǒng)一的接口規(guī)范來進(jìn)行數(shù)據(jù)的交互。
目前,要使應(yīng)用在開發(fā)過程中前后端分離,在設(shè)計實現(xiàn)統(tǒng)一通用接口方面,最佳實踐是采用REST規(guī)范。
2 REST規(guī)范介紹
2.1 定義
REST是“REpresentational State Transfer”的縮寫,中文翻譯成“表現(xiàn)狀態(tài)轉(zhuǎn)換”【1】。該規(guī)范由2000年Roy Thomas Fielding博士提出。該規(guī)范并不是一種新技術(shù)的或者新組件或者新服務(wù)的創(chuàng)造,而是一種理念的創(chuàng)新,將現(xiàn)有的WEB技術(shù)特征和能力進(jìn)行整合,使其符合一些準(zhǔn)則和約束。如果一個架構(gòu)符合REST規(guī)范,就稱它為RESTful架構(gòu)【3】。
2.2 資源
與面向?qū)ο蟮木幊陶Z言中一切都是對象一樣,在REST規(guī)范的世界里,一切都是資源;而與編程語言中的對象不一樣的是,在REST規(guī)范中,資源只定義了有限的方法。理解REST規(guī)范的重點在于理解什么是資源。可以把資源理解成一種對象,包括對象的類型、數(shù)據(jù)、關(guān)系、操作等等。
資源要能夠被識別,就需要給每個資源分配一個唯一的標(biāo)識。在REST規(guī)范中,這個唯一的標(biāo)識是URI(Uniform Resource Identifier)【1】。URI的最大特點是可讀性強,能夠降低前后端開發(fā)人員的溝通次數(shù),提高效率。例如:http://www.xxx.abc/employees/c001表示的是編號為001的員工。
2.3 資源接口統(tǒng)一
REST規(guī)范規(guī)定要使用統(tǒng)一的接口原則,也就是上文提到的資源只限定了有限的方法,無論什么資源,都可以通過使用限定的這幾類方法進(jìn)行資源的訪問。REST中規(guī)定了六種類型的請求方式:GET、POST、PUT、DELETE、HEAD、OPTIONS,正好與CRUD(Create-Retrieve-Update-Delete,增刪改查)四種操作相對應(yīng),例如,GET(查)、POST(增)、PUT(改)、DELETE(刪)。例如:
[REST請求 描述 GET:/employees 獲取所有員工的信息 GET:/employees/001 獲取ID為001的員工信息 PUT:/employees/001 更新ID為001的員工信息 DELETE:/employees/001 刪除ID為001的員工信息 POST:/employees/001 創(chuàng)建ID為001的員工信息 ]
2.4 具體約束
REST規(guī)定了4個約束:
l 每個資源擁有一個標(biāo)識,這個標(biāo)識可以用來唯一的標(biāo)明該資源
l 消息具備自描述性
l 資源的自描述性
l HTTP超媒體作為應(yīng)用狀態(tài)引擎
上圖是一個典型的服務(wù)端返回的結(jié)果信息,從結(jié)果信息中可以得知下一步的操作信息,該向哪個URL發(fā)送請求,還能知道資源的描述情況、唯一標(biāo)識是什么以及采用什么消息格式進(jìn)行交互理解的。所以,一個典型的REST規(guī)范形成的服務(wù),不需要額外的接口描述文檔,直接通過服務(wù)器端返回的信息,即可知道在該資源上能進(jìn)行哪些操作。這可以縮短前后端開發(fā)人員的交流成本。
3 接口設(shè)計與實現(xiàn)
3.1 Django-REST-Framework介紹
Django REST framework是一個基于Django的用于創(chuàng)建網(wǎng)絡(luò)應(yīng)用通用接口的REST框架,功能強大且靈活【2】。具備以下特點:
l 對開發(fā)人員友好的可視網(wǎng)絡(luò)通用接口
l 具備權(quán)限管理模塊
l 序列化同時支持ORM和非ORM數(shù)據(jù)源
l 采用功能性視圖即可自定義所有通用接口
l 有強大的社區(qū)支持
l 應(yīng)用廣泛,包括Mozilla,Red Hat等
3.2 接口設(shè)計及實現(xiàn)
3.2.1 環(huán)境搭建及數(shù)據(jù)序列化
作為實驗,強烈建議創(chuàng)建一個與真是環(huán)境隔離的實驗環(huán)境,本接口設(shè)計采用Python3自帶的venv創(chuàng)建虛擬環(huán)境,并安裝好相關(guān)包及依賴包,涉及django和djangorestframework。其中,django用于按照我們熟悉的開發(fā)架構(gòu),去涉及開發(fā)符合REST規(guī)范的通用程序接口,而djangorestframework則可以看成是該框架下的一個APP,只需要將rest_framework添加到INSTALLED_APPS中即可,簡單快捷。
通常情況下,前端從調(diào)用后臺API,API肯定需要返回數(shù)據(jù)給前端,返回的數(shù)據(jù)必須具有統(tǒng)一的格式,目前主流用的比較多的是JSON,可能有少部分還在用XML。具體到djangorestframework中,序列化就是將數(shù)據(jù)實例信息(Model信息)自動轉(zhuǎn)換為JSON,而且也可以將前端傳給后臺的JSON數(shù)據(jù)轉(zhuǎn)換為python的數(shù)據(jù)類型(dict/list/set等)。舉個簡單的例子:
序列化之前:
classBookSerializer(serializers.ModelSerializer):
tracks = serializers.StringRelatedField(many=True)
class Meta:
model = Book
fields = ('writer', 'price', 'public')
序列化之后:
{ 'writer': 'libai',
‘price: ‘$65,
'public': ‘sanhe,
}
3.2.2 請求和響應(yīng)
請求和響應(yīng)是REST framework的核心部分,是上一章提到的基于HTTP請求與響應(yīng)的具體實現(xiàn)。
在請求部分,在djangorestframework框架中,Request對象負(fù)責(zé)所有的請求工作。該對象繼承自普通的HttpRequest,但更靈活。在Request對象中,最核心的是request.data屬性,比Django中的Request.POST更加靈活,能處理更多的請求。Request.POST只能采用POST方法去處理相關(guān)表單(form)數(shù)據(jù),而request.Data則可以采用‘POST、‘PUT、‘PATCH等方法處理任意數(shù)據(jù)。
在響應(yīng)部分,Response對象負(fù)責(zé)所有相關(guān)操作,是一種模板響應(yīng),將純粹的內(nèi)容返還給客戶端去展示。具體的返回數(shù)據(jù)的形式則可以通過內(nèi)容協(xié)商來決定。在代碼中,return Response(data)即可完成響應(yīng)。
需要注意的是,響應(yīng)時,經(jīng)常會出現(xiàn)各種異常響應(yīng),就好比在瀏覽網(wǎng)頁時,經(jīng)常出現(xiàn)404等代碼,稱之為狀態(tài)碼。這些狀態(tài)碼,就是響應(yīng)對象提供的。在djangorestframework框架中,有著非常人性化的涉及,狀態(tài)碼并不是一堆數(shù)字的堆砌,而是提供了更加明確的標(biāo)識,比如HTTP_404_NOT_FOUND等。下面是一個具體的代碼片段,用于實現(xiàn)請求和響應(yīng)。
@api_view(['GET', 'PUT', 'DELETE'])
defbook_detail(request, pk):
"""
讀取, 更新或刪除。
"""
try:
book = Book.objects.get(pk=pk)
exceptBook.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
ifrequest.method == 'GET':
serializer = BookSerializer(book)
return Response(serializer.data)
elifrequest.method == 'PUT':
serializer = BookSerializer(book, data=request.data)
ifserializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elifrequest.method == 'DELETE':
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
代碼中提到的@api_view是djangorestframework提供的通用視圖的封裝,這些封裝的視圖,提供了確保視圖能夠收到Request實例,將內(nèi)容賦予Response對象等一些基本功能。
上述的代碼片段跟開發(fā)Django應(yīng)用時采用的視圖很相似,但視圖中請求/響應(yīng)的內(nèi)容類型已經(jīng)不需要明確解析/定義,request.data會對輸入的json請求進(jìn)行自行處理。
3.2.3 認(rèn)證和權(quán)限
認(rèn)證和權(quán)限是一個通用接口設(shè)計過程中不可缺少的一部分。通過認(rèn)證,可以保障接口的安全使用,而權(quán)限則能將一些敏感信息保護(hù)起來,特別是刪除權(quán)限,不能隨便調(diào)用。基于djangorestframework框架來添加接口認(rèn)證及權(quán)限設(shè)置需要以下幾方面工作:
l 將序列化的模型與其創(chuàng)建者相互關(guān)聯(lián)
l 只有經(jīng)過身份驗證(登錄)的用戶才可以創(chuàng)建模型
l 只有創(chuàng)建該模型的用戶才可以對其進(jìn)行更改或者刪除
l 未經(jīng)驗證的用戶只具有訪問(只讀)的功能
模型與創(chuàng)建者的關(guān)聯(lián),在具體程序?qū)崿F(xiàn)上,只需要在model模塊增加所有者字段,后臺的效果就是在數(shù)據(jù)庫中增加了一個該模型的所有者字段,與開發(fā)Django應(yīng)用時無差別;在權(quán)限的控制上,可以用框架提供的permissions模塊,通過該模塊即可完成數(shù)據(jù)模型的精細(xì)化控制,比如通過permission_classes = (permissions.IsAuthenticatedOrReadOnly,)即可實現(xiàn)只有登錄的用戶才有權(quán)限創(chuàng)建修改,否則只有讀的權(quán)限。
3.2.4 小結(jié)
Djangorestframework框架的功能非常豐富,限于篇幅,只介紹了三個在設(shè)計實現(xiàn)通用接口時必備的功能模塊,有了數(shù)據(jù)的序列化,就有了后臺數(shù)據(jù)與前臺數(shù)據(jù)相互交流的統(tǒng)一格式,一般采用json格式,通俗來講就是前后臺要用同一種語言,才能溝通;有了請求和響應(yīng),相當(dāng)于一種載體,有了這種載體,可以把前臺的數(shù)據(jù)送到后端,后端的數(shù)據(jù)可以發(fā)給前端,有來有去相互交互;權(quán)限認(rèn)證則是為了能夠保障接口的安全性,后臺數(shù)據(jù)是敏感的,設(shè)計一個通用接口時,認(rèn)證和權(quán)限模塊必不可少。
4 結(jié)論
本文介紹了目前流行的REST規(guī)范,目的是應(yīng)用該規(guī)范設(shè)計開發(fā)通用程序接口;介紹了基于Django的REST規(guī)范框架djangorestframework,該框架提供了豐富的類,能快速、簡潔地實現(xiàn)符合REST規(guī)范的通用程序接口;以創(chuàng)建一個圖書數(shù)據(jù)管理通用接口為例,介紹了在接口實現(xiàn)過程中必備的三個模塊及具體實現(xiàn)方法,供開發(fā)人員做參考設(shè)計。
參考文獻(xiàn):
[1] 趙震一,李哲.RESTful Web APIs中文版[M].北京:電子工業(yè)出版社,2014.
[2] http://www.django-rest-framework.org/.
[3] 郭理勇.RESTful API開發(fā)實戰(zhàn)[M].北京:清華大學(xué)出版社,2018.
【通聯(lián)編輯:唐一東】