[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-DIuZRcLc-1635934913862)(image-20210831100921267.png)]
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rdtYnJsZ-1635934913863)(image-20210831100951626.png)]
為了在團隊內部形成共識、防止個人習慣差異引起的混亂,我們需要找到一種大家都覺得很好的接口實現規范,而且這種規范能夠讓後端寫的接口,用途一目了然,減少雙方之間的合作成本。
通過網絡,規定了前後端信息交互規則的url鏈接,也就是前後端信息交互的媒介
Web API接口和一般的url鏈接還是有區別的,Web API接口簡單概括有下面四大特點
[]: https://api.map.baidu.com/place/v2/search
請求方式:get、post、put、patch、delete
請求參數:json或xml格式的key-value類型數據
""" ak:6E823f587c95f0148c19993539b99295 region:上海 query:肯德基 output:json """
響應結果:json或xml格式的數據
# xml格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295®ion=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=xml
#json格式
https://api.map.baidu.com/place/v2/search?ak=6E823f587c95f0148c19993539b99295®ion=%E4%B8%8A%E6%B5%B7&query=%E8%82%AF%E5%BE%B7%E5%9F%BA&output=json
{
"status":0,
"message":"ok",
"results":[
{
"name":"肯德基(羅餐廳)",
"location":{
"lat":31.415354,
"lng":121.357339
},
"address":"月羅路2380號",
"province":"上海市",
"city":"上海市",
"area":"寶山區",
"street_id":"339ed41ae1d6dc320a5cb37c",
"telephone":"(021)56761006",
"detail":1,
"uid":"339ed41ae1d6dc320a5cb37c"
}
...
]
}
Postman是一款接口調試工具,是一款免費的可視化軟件,同時支持各種操作系統平台,是測試接口的首選工具。
Postman可以直接從官網:https://www.getpostman.com/downloads/下載獲得,然後進行傻瓜式安裝。
REST全稱是Representational State Transfer,中文意思是表述(編者注:通常譯為表征性狀態轉移)。 它首次出現在2000年Roy Fielding的博士論文中。
RESTful是一種定義Web API接口的設計風格,尤其適用於前後端分離的應用模式中。
這種風格的理念認為後端開發任務就是提供數據的,對外提供的是數據資源的訪問接口,所以在定義接口時,客戶端訪問的URL路徑就表示這種要操作的數據資源。
事實上,我們可以使用任何一個框架都可以實現符合restful規范的API接口。
url鏈接一般都采用https協議進行傳輸
注:采用https協議,可以提高數據交互過程中的安全性
用api關鍵字標識接口url:
注:看到api字眼,就代表該請求url鏈接是完成前後台數據交互的
在url鏈接中標識數據版本
注:url鏈接中的v1、v2就是不同數據版本的體現(只有在一種數據資源有多版本情況下)
接口一般都是完成前後台數據的交互,交互的數據我們稱之為資源
注:一般提倡用資源的復數形式,在url鏈接中獎勵不要出現操作資源的動詞,錯誤示范:https://api.baidu.com/delete-user
特殊的接口可以出現動詞,因為這些接口一般沒有一個明確的資源,或是動詞就是接口的核心含義
7.1 正常響應
7.2 重定向響應
7.3 客戶端異常
7.4 服務器異常
{
error: "無權限操作"
}
GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔
# Hypermedia API,RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什麼
{
"status": 0,
"msg": "ok",
"results":[
{
"name":"肯德基(羅餐廳)",
"img": "https://image.baidu.com/kfc/001.png"
}
...
]
}
比較好的接口返回
# 響應數據要有狀態碼、狀態信息以及數據本身
{
"status": 0,
"msg": "ok",
"results":[
{
"name":"肯德基(羅餐廳)",
"location":{
"lat":31.415354,
"lng":121.357339
},
"address":"月羅路2380號",
"province":"上海市",
"city":"上海市",
"area":"寶山區",
"street_id":"339ed41ae1d6dc320a5cb37c",
"telephone":"(021)56761006",
"detail":1,
"uid":"339ed41ae1d6dc320a5cb37c"
}
...
]
}
api接口開發,最核心最常見的一個過程就是序列化,所謂序列化就是把數據轉換格式,序列化可以分兩個階段:
序列化: 把我們識別的數據轉換成指定的格式提供給別人。
例如:我們在django中獲取到的數據默認是模型對象,但是模型對象數據無法直接提供給前端或別的平台使用,所以我們需要把數據進行序列化,變成字符串或者json數據,提供給別人。
反序列化:把別人提供的數據轉換/還原成我們需要的格式。
例如:前端js提供過來的json數據,對於python而言就是字符串,我們需要進行反序列化換成模型類對象,這樣我們才能把數據保存到數據庫中。
核心思想: 縮減編寫api接口的代碼
Django REST framework是一個建立在Django基礎之上的Web 應用開發框架,可以快速的開發REST API接口應用。在REST framework中,提供了序列化器Serialzier的定義,可以幫助我們簡化序列化與反序列化的過程,不僅如此,還提供豐富的類視圖、擴展類、視圖集來簡化視圖的編寫工作。REST framework還提供了認證、權限、限流、過濾、分頁、接口文檔等功能支持。REST framework提供了一個API 的Web可視化界面來方便查看測試接口。
在Django裡使用restframework需要在INSTALLED_APPS裡添加"rest_framework"
接下來就可以使用DRF提供的功能進行api接口開發了。在項目中如果使用rest_framework框架實現API接口,主要有以下三個步驟:
# urls.py
path('bookview/',views.bookview.as_view()),
# views.py
from rest_framework.views import View
class bookview(View):
def get(self):
return HttpResponse('ok')
""" 進入View源碼中,首先找到as_view方法 """
@classonlymethod # 類方法,直接由類調用
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs):
………………
return self.dispatch(request, *args, **kwargs) # 此處調用了dispatch方法
return view # 將view方法返回
# dispatch方法(重要)
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
""" dispatch方法主要是對views.py裡的bookview裡的方法進行判斷 判斷其方法是否在http_method_names裡; http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] 如果存在使用getattr進行反射,此時的self便是bookview類 """
# urls.py
path('bookview/',views.bookview.as_view()),
# views.py
from rest_framework.views import APIView
class bookview(View):
def get(self):
return HttpResponse('ok')
""" 進入到APIView源碼裡 """
class APIView(View):
……
@classmethod
def as_view(cls, **initkwargs):
……
view = super().as_view(**initkwargs)
view.cls = cls
view.initkwargs = initkwargs
# Note: session based authentication is explicitly CSRF validated,
# all other authentication is CSRF exempt.
return csrf_exempt(view)
""" 能夠看到APIView實際上就是繼承View,並且直接繼承了View裡的as_view方法絲毫未改 唯獨有一點不同就是return csrf_exempt(view) 在django的中間間中有這樣一行代碼'django.middleware.csrf.CsrfViewMiddleware', 這便是防止csrf跨站請求偽造的 而csrf_exempt(view)就是@csrf_exempt裝飾器的另一種寫法,兩者一摸一樣 """
# 請求來了,會執行views.BookView.as_view()(request)---->觸發APIView的as_view
@classmethod
def as_view(cls, **initkwargs):
view = super().as_view(**initkwargs) # 調用了View的as_view
return csrf_exempt(view) # 去掉了csrf的認證,跟原來加裝飾器一樣
# 假設get請求來了,執行view()--最重要的-->self.dispatch()--》APIView的
def dispatch(self, request, *args, **kwargs):
# 把原來的request對象,包裝成了新的request對象,是drf的request
request = self.initialize_request(request, *args, **kwargs)
try:
# 執行了三大認證:認證,權限,頻率
self.initial(request, *args, **kwargs)
# 跟原來一模一樣
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 真正的執行視圖類中的方法,如果有異常,被捕獲了
response = handler(request, *args, **kwargs)
except Exception as exc:
response = self.handle_exception(exc)
return self.response
# 重點:
apiview:干了三件事
-把老的request對象包裝成了新的request對象
-通過APIView的initialize_request,包裝的
-以後再在視圖類中用的request對象,都是新的
-在執行視圖類中的方法之前,執行了三大認證
self.perform_authentication(request)
self.check_permissions(request)
self.check_throttles(request)
-處理全局異常
只要繼承了APIView,以後用的request對象,就是drf的request對象了
在執行視圖類的方法之前,會先執行三大認證,如果有異常,會被捕獲並處理
# view.py
from rest_framework.request import Request
from rest_framework.views import APIView
class bookview(APIView):
def get(self,request):
return HttpResponse('ok')
""" # from rest_framework.request import Request # 重點 -老的django的request在drf的request._request中 -新的request用起來跟原來一模一樣用,沒有一點區別 -對象.屬性,會觸發類的 __getattr__方法 -重寫了__getattr__ return getattr(self._request, attr) -新的request多個一個data屬性--》所有post提交的數據,都放在它中 """