一、rest api a、api就是介面 如: - http://www.oldboyedu.com/get_user/ - http://www.oldboyedu.com/get_users/ b、api的兩個用途 1、為別人提供服務 2、前後端分離 二、restful a、--字面意思:表徵狀 ...
一、rest api
a、api就是介面
如: - http://www.oldboyedu.com/get_user/
- http://www.oldboyedu.com/get_users/
b、api的兩個用途
1、為別人提供服務
2、前後端分離
二、restful
a、--字面意思:表徵狀態轉移
b、面向資源編程,對互聯網上的任意東西都視為資源
如:- http://www.oldboyedu.com/get_user/
- http://www.oldboyedu.com/get_img/1.png
三、restful規範
a、 ---URL
b、 ---url名詞
路徑,視網路上任何東西都是資源,均使用名詞表示(可複數) https://api.example.com/v1/zoos https://api.example.com/v1/animals https://api.example.com/v1/employee
c、 ---status狀態碼
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 - [*]:伺服器發生錯誤,用戶將無法判斷發出的請求是否成功。
d、---提交方式
GET :從伺服器取出資源(一項或多項)
POST :在伺服器新建一個資源
PUT :在伺服器更新資源(客戶端提供改變後的完整資源)
PATCH :在伺服器更新資源(客戶端提供改變的屬性)
DELETE :從伺服器刪除資源
e、 ---錯誤信息
狀態碼是4xx時,應返回錯誤信息,error當做key。 { error: "Invalid API key" }
f、 ---版本
g、 ---Hypermedia link,RESTful API最好做到Hypermedia,即返回結果中提供鏈接,連向其他API方法,使得用戶不查文檔,也知道下一步應該做什麼。
h、---功能變數名稱
j、---過濾,通過在url上傳參的形式傳遞搜索條件
k、 ---返回結果,針對不同操作,伺服器向用戶返回的結果應該符合以下規範
GET /collection:返回資源對象的列表(數組) GET /collection/resource:返回單個資源對象 POST /collection:返回新生成的資源對象 PUT /collection/resource:返回完整的資源對象 PATCH /collection/resource:返回完整的資源對象 DELETE /collection/resource:返回一個空文檔
rest_Framework的規範:
按順序:它的method的不同,原來沒有考慮,原來是url區分,現在通過method來區分,method的不同提交方式不同,緊接著一般是面向資源的就是把url變成名詞,接下就是返回值,以前沒有考慮狀態碼,現在有考慮狀態碼。(一般有get,post方法,還有put,delete等方法)
四、 基於Django Rest Framework框架實現
a、安裝:pip3 install djangorestframework -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com
五、什麼是RESTful
- REST與技術無關,代表的是一種軟體架構風格,REST是Representational State Transfer的簡稱,中文翻譯為“表徵狀態轉移”
- REST從資源的角度類審視整個網路,它將分佈在網路中某個節點的資源通過URL進行標識,客戶端應用通過URL來獲取資源的表徵,獲得這些表徵致使這些應用轉變狀態
- REST與技術無關,代表的是一種軟體架構風格,REST是Representational State Transfer的簡稱,中文翻譯為“表徵狀態轉移”
- 所有的數據,不過是通過網路獲取的還是操作(增刪改查)的數據,都是資源,將一切數據視為資源是REST區別與其他架構風格的最本質屬性
- 對於REST這種面向資源的架構風格,有人提出一種全新的結構理念,即:面向資源架構(ROA:Resource Oriented Architecture)
a、 django的中間件比rest_framework執行的早
b、 認證的功能放到中間件也是可以做的
c、認證一般做,檢查用戶是否存在,如果存在request.user/request.auth;不存在request.user/request.auth=None
d、認證小總結:
---類:authenticate/authenticate_header ---返回值:None,元組(user,auth),異常 ---配置: ---視圖: class IndexView(APIView): authentication_classes = [MyAuthentication,] ---全局 REST_FRAMEWORK = { 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, "DEFAULT_AUTHENTICATION_CLASSES": [ # "app02.utils.MyAuthentication", ], }
六、許可權
a、許可權才真正的做request.user/request.auth拿到它們做是否訪問的判斷
b、許可權小總結:
---類: has_permission/has_object_permission ---返回值:True、False、exceptions.PermissionDenied(detail="錯誤信息") ---配置: ---視圖: class IndexView(APIView): permission_classes = [MyPermission,] ---全局: REST_FRAMEWORK = { "DEFAULT_PERMISSION_CLASSES": [ # "app02.utils.MyAuthentication", ], }
七、限制訪問的頻率
限制訪問頻率的應用:
a、對匿名用戶進行限制,每個用戶1分鐘允許訪問10次
在這裡用唯一標識:self.get_ident()
b、限制訪問的頻率小總結:
---類: allow_request/wait PS: scope = "wdp_user" ---返回值:True、False ---配置: ---視圖: class IndexView(APIView): throttle_classes=[AnonThrottle,UserThrottle,] def get(self,request,*args,**kwargs): self.dispatch return Response('訪問首頁') ---全局: REST_FRAMEWORK = { "DEFAULT_THROTTLE_CLASSES":[ ], 'DEFAULT_THROTTLE_RATES':{ 'wdp_anon':'5/minute', 'wdp_user':'10/minute', } }
八、認證、許可權、限制訪問頻率返回結果的比較
1、認證、許可權、限制訪問頻率這三個返回的結果:
a、認證返回的三種結果:
a、None
b、元組(user,auth)
c、異常 raise APIException(...)
b、 許可權的返回值三種結果:
a、True 有許可權
b、False 沒許可權
c、異常
c、 限制訪問的頻率返回值的兩種結果:
a、True
b、False
實例化: v1 = ["view.xxx.path.Role","view.xxx.path.Group",] 可以迴圈,迴圈出來的每一個不能實例化 如果把v1迴圈弄成每一個對象列表,通過rsplit切割,在通過importlib.import_module拿到每一個路徑,在通過getattr把它的類名拿過來, 這個類加括弧就是實例化想 for item in v1: m = importlib.import_module('view.xxx.path') cls = getattr(m,'Role') cls() from view.xxx.path import Role,Group v2 = [Group,Role] 這個可以迴圈每一個實例化 for item in v2: #迴圈V2的每一個元素加括弧,就是實例化 item()
九、Django rest_Framework框架
a、 ----為什麼用Django rest_Framework框架?
----首先沒有Django rest_Framework框架用django也是可以做出來的,只不過它為我們提供一些API常用的功能,比如:(認證,許可權,限流,有了這些我們只需要寫個類已配置,
它就能當都市圖用,還能全局配置,如果自己寫還得寫中間件,寫裝飾器來實現,通過Django rest_Framework框架,他已經把規則寫好,只需要寫類,只需實現方法,返回值就可以)
實現了一部分功能。 ----設計比較好 ----單獨視圖+全局配置 =>Dajngo中間件(importlib/反射)=>動態配置課擴展(簡訊,郵件,微信等提醒)
b、Django rest_Framework原理?
先開始在路由,路由.as_view,
點擊as_view
請求進來,走完以上,才走self.dispatch()
走self.dispatch()流程如下地址:http://www.cnblogs.com/mengqingjian/p/8419563.html
十、版本
a、根據url的不同來來操作,版本控制
先在setting中註冊
十一、rest framework解析器
a、請求的數據進行解析:請求體進行解析。表示服務端可以解析的數據格式的種類。
Content-Type: application/url-encoding..... request.body request.POST Content-Type: application/json..... request.body request.POST 客戶端: Content-Type: application/json '{"name":"alex","age":123}' 服務端接收: 讀取客戶端發送的Content-Type的值 application/json parser_classes = [JSONParser,] media_type_list = ['application/json',] 如果客戶端的Content-Type的值和 application/json 匹配:JSONParser處理數據 如果客戶端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser處理數據 配置: 單視圖: class UsersView(APIView): parser_classes = [JSONParser,] 全局配置: REST_FRAMEWORK = { 'VERSION_PARAM':'version', 'DEFAULT_VERSION':'v1', 'ALLOWED_VERSIONS':['v1','v2'], # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning" 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_PARSER_CLASSES':[ 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', ] }
十二、 rest framework序列化+Form
a、序列化:
對象 -> 字元串 序列化
字元串 -> 對象 反序列化
b、目的:
解決QuerySet序列化問題
十三、為什麼要前後端分離
a、因為前端它有自己框架,這樣它的效率就非常高
b、不做前後端分離,公司如果既有客戶端,又有app這種情況下你就的寫兩遍
十四、django restful框架好處
幫助我們寫了好多組件比如:
a、認證:有類,類中的方法authenticate/authenticate_header,它的返回值有None,元組,異常。如果返回值為None那就不管,它是匿名用戶。
b、許可權:有類,類中的方法:has_permission
c、節流:有類,類的方法:allow_request,在這裡allow_request來表示限制,它是通過IP來限制,
它的內部原理是:預設是IP,用戶來用IP,這個IP可能代理IP,IP或者是代理IP拿著請求頭預設放到大家能夠的緩存中
去,每一個人的IP為p,後面的那個列表存它的方位時間,每一次請求進來獲取它的當前時間根據時間的個數來比較,在
比較的過程中看看把不符合時間的個數來進行比較,能訪問就繼續,不能訪問就不要繼續。
d、版本:是url和hostname,他們兩個鐘每一個都有兩個方法一個是幫你拿版本另一個是幫你反向生成url
e、解析器:用戶發過來的請求體數據進行操作
f、序列化:兩個功能:序列化,校驗
十五、分頁
分頁的三種情況:
a、記錄當前訪問頁的數據id
b、最多顯示120頁
c、對頁碼進行加密
a、基於limit offset做分頁
class P1(LimitOffsetPagination): max_limit = 3 default_limit = 2 limit_query_param = 'limit' offset_query_param = 'offset' class IndexView(views.APIView): def get(self,request,*args,**kwargs): user_list = models.UserInfo.objects.all() p1 = P1() page_user_list = p1.paginate_queryset(queryset=user_list, request=request, view=self) ser = IndexSerializer(instance=page_user_list, many=True) return Response(ser.data) # 不含上一頁和下一頁 # return p1.get_paginated_response(ser.data) # 含上一頁和下一頁 class IndexView(views.APIView): def get(self,request,*args,**kwargs): ret = BaseResponse() try: user_list = models.UserInfo.objects.all() p1 = P1() page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self) ser = IndexSerializer(instance=page_user_list,many=True) ret.data = ser.data ret.next = p1.get_next_link() except Exception as e: ret.code= 1001 ret.error = 'xxxx錯誤' return Response(ret.__dict__)
b. 基於頁碼的分頁
class P2(PageNumberPagination): # 每頁顯示的數據條數 max_page_size = 5 page_size = 2 page_size_query_param = 'size' # 頁碼 page_query_param = 'page'
十六、視圖
1、APIView
class IndexView(views.APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all() ser = IndexSerializer(instance=user_list,many=True) return Response(ser.data)
2、GenericAPIview(APIView)
3、GenericViewSet(ViewSetMixin,generics.GenericAPIView)
路由修改: urlpatterns = [ url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})), url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view({'get':'retrieve'})), ] 視圖修改: class IndexView(viewsets.GenericViewSet): def list(self,request,*args,**kwargs): pass # 獲取列表信息 def retrieve(self, request, *args, **kwargs): pass # 獲取單條數據 def create(self,request, *args, **kwargs): pass 自定義: 增 POST /users/ 刪 DELETE /users/1/ 改 PUT /users/1/ patch /users/1/ 查 GET /users/ GET /users/1/ urlpatterns = [ url(r'^index/$', views.IndexView.as_view()), url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view()), ] class IndexView(views.APIView): def get(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: pass # 獲取單條信息 else: pass # 獲取列表信息 def post(self,request,*args,**kwargs): pass def put(self,request,*args,**kwargs): pass def patch(self,request,*args,**kwargs): pass def delete(self,request,*args,**kwargs): pass
4、ModelViewSet
ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet) class IndexView(ModelViewSet):
十七、 渲染器
看到的頁面時什麼樣子的,返回數據。
renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
十八、跨域
a、 瀏覽器的同源策略
1、 ----對ajax請求進行阻攔
2、 ----對href屬性讀不阻攔
xhr=new XMLHttpRequest
xhr.open...
xhr.send(...)
b、 解決方案:
---JSONP
點擊按鈕:
動態添加一個
<script src='http://www.baidu.com/users/'></script> <script> function func(arg){ alert(arg) } </script
c、刪除
<script src='http://www.baidu.com/users/'></script>