張?jiān)骑w 楊明光
摘要:隨著網(wǎng)站開(kāi)發(fā)技術(shù)的發(fā)展,前后端分離的設(shè)計(jì)方法已經(jīng)成為主流技術(shù)路線(xiàn),這種方式一方面能夠使開(kāi)發(fā)工作精細(xì)化,前后端開(kāi)發(fā)人員各司其職,互不干擾,另一方面使整個(gè)系統(tǒng)易于維護(hù)和擴(kuò)展。這種開(kāi)發(fā)模式的關(guān)鍵在于后端開(kāi)發(fā)人員要設(shè)計(jì)出一個(gè)簡(jiǎn)潔、清晰、權(quán)限分明的通用程序接口,用于與系統(tǒng)前端程序進(jìn)行數(shù)據(jù)交互。本文通過(guò)對(duì)目前最流行的REST(Representational State Transfer)規(guī)范的研究,實(shí)現(xiàn)通用程序接口設(shè)計(jì)與開(kāi)發(fā),進(jìn)而實(shí)現(xiàn)應(yīng)用開(kāi)發(fā)的前后端分離。REST規(guī)范能有效降低開(kāi)發(fā)人員的溝通成本。Django是采用Python編寫(xiě)的網(wǎng)絡(luò)程序設(shè)計(jì)框架,采用Django框架能極大的簡(jiǎn)化通用程序接口設(shè)計(jì)的工作量。
關(guān)鍵詞:Django;RESTful;網(wǎng)絡(luò)通用接口
中圖分類(lèi)號(hào):TP391 文獻(xiàn)標(biāo)識(shí)碼:A 文章編號(hào):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 引言
在移動(dòng)互聯(lián)網(wǎng)時(shí)代,各類(lèi)終端設(shè)備如潮水般涌現(xiàn),如常見(jiàn)的各類(lèi)PAD,各種尺寸的Mobile,還有已經(jīng)久經(jīng)沙場(chǎng)的各類(lèi)PC。這些設(shè)備給使用人員帶去了便利,但是對(duì)于開(kāi)發(fā)人員來(lái)講卻是噩夢(mèng)的開(kāi)始。以往采用瀏覽器的響應(yīng)方式很顯然已經(jīng)無(wú)法滿(mǎn)足用戶(hù)對(duì)高用戶(hù)體驗(yàn)的要求。如何將開(kāi)發(fā)的應(yīng)用快速適配到各類(lèi)型設(shè)備,盡可能地減少開(kāi)發(fā)人員的工作量,提升效率,快速形成生產(chǎn)力,是對(duì)開(kāi)發(fā)人員提成的最迫切的要求?;诖?,前后端分離的需求越來(lái)越被重視,前端與用戶(hù)打交道,負(fù)責(zé)展現(xiàn)數(shù)據(jù)與用戶(hù)交互;后端負(fù)責(zé)業(yè)務(wù)和相關(guān)數(shù)據(jù)的處理,前后端通過(guò)統(tǒng)一的接口規(guī)范來(lái)進(jìn)行數(shù)據(jù)的交互。
目前,要使應(yīng)用在開(kāi)發(fā)過(guò)程中前后端分離,在設(shè)計(jì)實(shí)現(xiàn)統(tǒng)一通用接口方面,最佳實(shí)踐是采用REST規(guī)范。
2 REST規(guī)范介紹
2.1 定義
REST是“REpresentational State Transfer”的縮寫(xiě),中文翻譯成“表現(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è)架構(gòu)符合REST規(guī)范,就稱(chēng)它為RESTful架構(gòu)【3】。
2.2 資源
與面向?qū)ο蟮木幊陶Z(yǔ)言中一切都是對(duì)象一樣,在REST規(guī)范的世界里,一切都是資源;而與編程語(yǔ)言中的對(duì)象不一樣的是,在REST規(guī)范中,資源只定義了有限的方法。理解REST規(guī)范的重點(diǎn)在于理解什么是資源。可以把資源理解成一種對(duì)象,包括對(duì)象的類(lèi)型、數(shù)據(jù)、關(guān)系、操作等等。
資源要能夠被識(shí)別,就需要給每個(gè)資源分配一個(gè)唯一的標(biāo)識(shí)。在REST規(guī)范中,這個(gè)唯一的標(biāo)識(shí)是URI(Uniform Resource Identifier)【1】。URI的最大特點(diǎn)是可讀性強(qiáng),能夠降低前后端開(kāi)發(fā)人員的溝通次數(shù),提高效率。例如:http://www.xxx.abc/employees/c001表示的是編號(hào)為001的員工。
2.3 資源接口統(tǒng)一
REST規(guī)范規(guī)定要使用統(tǒng)一的接口原則,也就是上文提到的資源只限定了有限的方法,無(wú)論什么資源,都可以通過(guò)使用限定的這幾類(lèi)方法進(jìn)行資源的訪(fǎng)問(wèn)。REST中規(guī)定了六種類(lèi)型的請(qǐng)求方式:GET、POST、PUT、DELETE、HEAD、OPTIONS,正好與CRUD(Create-Retrieve-Update-Delete,增刪改查)四種操作相對(duì)應(yīng),例如,GET(查)、POST(增)、PUT(改)、DELETE(刪)。例如:
[REST請(qǐng)求 描述 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個(gè)約束:
l 每個(gè)資源擁有一個(gè)標(biāo)識(shí),這個(gè)標(biāo)識(shí)可以用來(lái)唯一的標(biāo)明該資源
l 消息具備自描述性
l 資源的自描述性
l HTTP超媒體作為應(yīng)用狀態(tài)引擎
上圖是一個(gè)典型的服務(wù)端返回的結(jié)果信息,從結(jié)果信息中可以得知下一步的操作信息,該向哪個(gè)URL發(fā)送請(qǐng)求,還能知道資源的描述情況、唯一標(biāo)識(shí)是什么以及采用什么消息格式進(jìn)行交互理解的。所以,一個(gè)典型的REST規(guī)范形成的服務(wù),不需要額外的接口描述文檔,直接通過(guò)服務(wù)器端返回的信息,即可知道在該資源上能進(jìn)行哪些操作。這可以縮短前后端開(kāi)發(fā)人員的交流成本。
3 接口設(shè)計(jì)與實(shí)現(xiàn)
3.1 Django-REST-Framework介紹
Django REST framework是一個(gè)基于Django的用于創(chuàng)建網(wǎng)絡(luò)應(yīng)用通用接口的REST框架,功能強(qiáng)大且靈活【2】。具備以下特點(diǎn):
l 對(duì)開(kāi)發(fā)人員友好的可視網(wǎng)絡(luò)通用接口
l 具備權(quán)限管理模塊
l 序列化同時(shí)支持ORM和非ORM數(shù)據(jù)源
l 采用功能性視圖即可自定義所有通用接口
l 有強(qiáng)大的社區(qū)支持
l 應(yīng)用廣泛,包括Mozilla,Red Hat等
3.2 接口設(shè)計(jì)及實(shí)現(xiàn)
3.2.1 環(huán)境搭建及數(shù)據(jù)序列化
作為實(shí)驗(yàn),強(qiáng)烈建議創(chuàng)建一個(gè)與真是環(huán)境隔離的實(shí)驗(yàn)環(huán)境,本接口設(shè)計(jì)采用Python3自帶的venv創(chuàng)建虛擬環(huán)境,并安裝好相關(guān)包及依賴(lài)包,涉及django和djangorestframework。其中,django用于按照我們熟悉的開(kāi)發(fā)架構(gòu),去涉及開(kāi)發(fā)符合REST規(guī)范的通用程序接口,而djangorestframework則可以看成是該框架下的一個(gè)APP,只需要將rest_framework添加到INSTALLED_APPS中即可,簡(jiǎn)單快捷。
通常情況下,前端從調(diào)用后臺(tái)API,API肯定需要返回?cái)?shù)據(jù)給前端,返回的數(shù)據(jù)必須具有統(tǒng)一的格式,目前主流用的比較多的是JSON,可能有少部分還在用XML。具體到djangorestframework中,序列化就是將數(shù)據(jù)實(shí)例信息(Model信息)自動(dòng)轉(zhuǎn)換為JSON,而且也可以將前端傳給后臺(tái)的JSON數(shù)據(jù)轉(zhuǎn)換為python的數(shù)據(jù)類(lèi)型(dict/list/set等)。舉個(gè)簡(jiǎn)單的例子:
序列化之前:
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 請(qǐng)求和響應(yīng)
請(qǐng)求和響應(yīng)是REST framework的核心部分,是上一章提到的基于HTTP請(qǐng)求與響應(yīng)的具體實(shí)現(xiàn)。
在請(qǐng)求部分,在djangorestframework框架中,Request對(duì)象負(fù)責(zé)所有的請(qǐng)求工作。該對(duì)象繼承自普通的HttpRequest,但更靈活。在Request對(duì)象中,最核心的是request.data屬性,比Django中的Request.POST更加靈活,能處理更多的請(qǐng)求。Request.POST只能采用POST方法去處理相關(guān)表單(form)數(shù)據(jù),而request.Data則可以采用‘POST、‘PUT、‘PATCH等方法處理任意數(shù)據(jù)。
在響應(yīng)部分,Response對(duì)象負(fù)責(zé)所有相關(guān)操作,是一種模板響應(yīng),將純粹的內(nèi)容返還給客戶(hù)端去展示。具體的返回?cái)?shù)據(jù)的形式則可以通過(guò)內(nèi)容協(xié)商來(lái)決定。在代碼中,return Response(data)即可完成響應(yīng)。
需要注意的是,響應(yīng)時(shí),經(jīng)常會(huì)出現(xiàn)各種異常響應(yīng),就好比在瀏覽網(wǎng)頁(yè)時(shí),經(jīng)常出現(xiàn)404等代碼,稱(chēng)之為狀態(tài)碼。這些狀態(tài)碼,就是響應(yīng)對(duì)象提供的。在djangorestframework框架中,有著非常人性化的涉及,狀態(tài)碼并不是一堆數(shù)字的堆砌,而是提供了更加明確的標(biāo)識(shí),比如HTTP_404_NOT_FOUND等。下面是一個(gè)具體的代碼片段,用于實(shí)現(xiàn)請(qǐng)求和響應(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實(shí)例,將內(nèi)容賦予Response對(duì)象等一些基本功能。
上述的代碼片段跟開(kāi)發(fā)Django應(yīng)用時(shí)采用的視圖很相似,但視圖中請(qǐng)求/響應(yīng)的內(nèi)容類(lèi)型已經(jīng)不需要明確解析/定義,request.data會(huì)對(duì)輸入的json請(qǐng)求進(jìn)行自行處理。
3.2.3 認(rèn)證和權(quán)限
認(rèn)證和權(quán)限是一個(gè)通用接口設(shè)計(jì)過(guò)程中不可缺少的一部分。通過(guò)認(rèn)證,可以保障接口的安全使用,而權(quán)限則能將一些敏感信息保護(hù)起來(lái),特別是刪除權(quán)限,不能隨便調(diào)用。基于djangorestframework框架來(lái)添加接口認(rèn)證及權(quán)限設(shè)置需要以下幾方面工作:
l 將序列化的模型與其創(chuàng)建者相互關(guān)聯(lián)
l 只有經(jīng)過(guò)身份驗(yàn)證(登錄)的用戶(hù)才可以創(chuàng)建模型
l 只有創(chuàng)建該模型的用戶(hù)才可以對(duì)其進(jìn)行更改或者刪除
l 未經(jīng)驗(yàn)證的用戶(hù)只具有訪(fǎng)問(wèn)(只讀)的功能
模型與創(chuàng)建者的關(guān)聯(lián),在具體程序?qū)崿F(xiàn)上,只需要在model模塊增加所有者字段,后臺(tái)的效果就是在數(shù)據(jù)庫(kù)中增加了一個(gè)該模型的所有者字段,與開(kāi)發(fā)Django應(yīng)用時(shí)無(wú)差別;在權(quán)限的控制上,可以用框架提供的permissions模塊,通過(guò)該模塊即可完成數(shù)據(jù)模型的精細(xì)化控制,比如通過(guò)permission_classes = (permissions.IsAuthenticatedOrReadOnly,)即可實(shí)現(xiàn)只有登錄的用戶(hù)才有權(quán)限創(chuàng)建修改,否則只有讀的權(quán)限。
3.2.4 小結(jié)
Djangorestframework框架的功能非常豐富,限于篇幅,只介紹了三個(gè)在設(shè)計(jì)實(shí)現(xiàn)通用接口時(shí)必備的功能模塊,有了數(shù)據(jù)的序列化,就有了后臺(tái)數(shù)據(jù)與前臺(tái)數(shù)據(jù)相互交流的統(tǒng)一格式,一般采用json格式,通俗來(lái)講就是前后臺(tái)要用同一種語(yǔ)言,才能溝通;有了請(qǐng)求和響應(yīng),相當(dāng)于一種載體,有了這種載體,可以把前臺(tái)的數(shù)據(jù)送到后端,后端的數(shù)據(jù)可以發(fā)給前端,有來(lái)有去相互交互;權(quán)限認(rèn)證則是為了能夠保障接口的安全性,后臺(tái)數(shù)據(jù)是敏感的,設(shè)計(jì)一個(gè)通用接口時(shí),認(rèn)證和權(quán)限模塊必不可少。
4 結(jié)論
本文介紹了目前流行的REST規(guī)范,目的是應(yīng)用該規(guī)范設(shè)計(jì)開(kāi)發(fā)通用程序接口;介紹了基于Django的REST規(guī)范框架djangorestframework,該框架提供了豐富的類(lèi),能快速、簡(jiǎn)潔地實(shí)現(xiàn)符合REST規(guī)范的通用程序接口;以創(chuàng)建一個(gè)圖書(shū)數(shù)據(jù)管理通用接口為例,介紹了在接口實(shí)現(xiàn)過(guò)程中必備的三個(gè)模塊及具體實(shí)現(xiàn)方法,供開(kāi)發(fā)人員做參考設(shè)計(jì)。
參考文獻(xiàn):
[1] 趙震一,李哲.RESTful Web APIs中文版[M].北京:電子工業(yè)出版社,2014.
[2] http://www.django-rest-framework.org/.
[3] 郭理勇.RESTful API開(kāi)發(fā)實(shí)戰(zhàn)[M].北京:清華大學(xué)出版社,2018.
【通聯(lián)編輯:唐一東】