import rest_framework from rest_framework.views import APIView from rest_framework.request import Request 在views.py中寫出合適的api類,只須要繼承rest_framework中generics中的某個類,重寫咱們須要的方法實現合適的邏輯便可
""" APIView的as_view(局部禁用csrf) =>走父級的as_view調用dispatch分發請求 =>APIView本身重寫了dispatch,使用本身完成分發 =>分發前完成request二次封裝、數據解析 =>三大認證 =>請求的實際響應(本身的視圖類的處理分發) =>出現了異常,就會交給異常模塊處理異常 =>響應模塊完成響應、渲染模塊能夠以json或瀏覽器兩種方式渲染 APIView請求生命週期 1)APIView類繼承View類,重寫了as_view和dispatch方法 2)重寫的as_view方法,主體仍是View的as_view,只是在返回視圖view函數地址時,局部禁用csrf認證 3)在執行請求邏輯前:請求模塊(二次封裝request)、解析模塊(三種數據包格式的數據解析) 在執行請求邏輯中:異常模塊(執行出任何異常交給異常模塊處理) 在執行請求邏輯後:響應模塊(二次封裝response)、渲染模塊(響應的數據能JSON和頁面兩種渲染) """
生命週期圖:django
""" request._request 被request徹底兼容 request.query_params | request.data 1)將wsgi的request對象轉化成drf的Request類的對象 2)封裝後的request對象徹底兼容wsgi的request對象,而且將原request保存在新的request._request 3)重寫格式化請求數據存放位置 拼接參數:request.query_params 數據包參數:request.data 源碼解析: 入口:APIVIew的dispatch方法的request=self.initialize_request(request,*args,**kwargs) print(request._request.method) 在內部將wsgi的request賦值給request._request print(request.method) 就是經過__getattr__走的是request._request.method print(request.query_params) 走的是方法屬性,就是給request._request.GET從新命名 print(request.data) 走的是方法屬性,值依賴於request._full_data """
""" 解析模塊:只處理數據包參數 -form-data,urlencoded,json 局部配置:parser_classes = [JSONParser, FormParser, MultiPartParser] 全局配置: 'DEFAULT_PARSER_CLASSES': [ 'rest_framework.parsers.JSONParser', 'rest_framework.parsers.FormParser', 'rest_framework.parsers.MultiPartParser' ], 1)全局配置全部視圖類的解析方式,解析配置能夠配置三種 2)局部配置當前視圖類的解析方式,解析配置能夠配置三種 3)配置的查找順序:局部(視圖類的類屬性) =>全局(settings文件的drf配置)=>默認(drf的默認配置) 注:該模塊瞭解,可是全局局部配置是重點 REST_FAMEWORK = { 全局配置解析類:適用於全部視圖類 'DEFAULT_PARSER_CLASSES': [ #'rest_framework.parsers.JSONParser', #'rest_framework.parsers.FormParser', #'rest_framework.parsers.MultiPartParser' ], } 源碼解析: 入口:APIVIew的dispatch方法的 request=self.initialize_request(request,*args,**kwargs) 獲取解析類:parsers = self.get_parsers(), 進行局部全局默認配置查找順序進行查找:return [parser() for parser in self.parser_classes] """
""" Response(data=常量|列表|字典,status=網絡狀態碼) data:響應數據 status:響應的網絡狀態碼 template_name:drf完成先後臺不分離返回頁面,可是就不能夠返回data(不須要了解) headers:響應頭,通常不規定,走默認 exception:通常異常響應,會將其設置成True,默認False(不設置也沒事) content_type:默認就是 application/json,不須要處理 """
""" 局部配置:renderer_classes = [JSONRenderer, BrowsableAPIRenderer] 全局配置: 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', 'rest_framework.renderers.BrowsableAPIRenderer', # 上線後儘可能關閉 ], 渲染模塊(瞭解):Postman請求結果是json,瀏覽器請求結果是頁面 能夠全局與局部配置 局部配置解析類:只適用於當前視圖類 parser_classes = [JSONParser, FormParser, MultiPartParser] 局部配置渲染類:只適用於當前視圖類 renderer_classes = [JSONRenderer, BrowsableAPIRenderer] def post(self, request, *args, **kwargs): print(request._request.method) # 在內部將wsgi的request賦值給request._request print(request.method) # 就是經過__getattr__走的是request._request.method print(request.query_params) # 走的是方法屬性,就是給request._request.GET從新命名 print(request.data) # 走的是方法屬性,值依賴於request._full_data return Response({ 'msg': 'apiview post ok' }) """
""" settings中配置:'EXCEPTION_HANDLER': 'api.exception.exception_handler', 重寫exception_handler方法: 必定要在settings文件中將異常模塊配置本身的異常處理函數 from rest_framework.views import exception_handler as drf_exception_handler from rest_framework.response import Response 先交個drf處理客戶端異常,若是結果response表明服務器異常,本身處理 最終必定要在日誌文件中記錄異常現象 def exception_handler(exc, context): response = drf_exception_handler(exc, context) detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc) if not response: # 服務端錯誤 response = Response({'detail': detail}) else: response.data = {'detail': detail} 核心:要將response.data.get('datail')信息記錄到日誌文件 logger.waringz(response.data.get('datail')) return response 源碼解析: 入口:APIVIew的handle_exception方法的 獲取異常函數:exception_handler = self.get_exception_handler() 提供額外參數:context = self.get_exception_handler_context() 默認的exception_handler函數只處理客戶端異常造成的response對象, 服務器異常不作處理 二次封裝事後的response,處理告終果渲染 """
from django.views import View from django.http import JsonResponse class BookView(View): def get(self, request, *args, **kwargs): return JsonResponse({ 'msg': 'view get ok' }) def post(self, request, *args, **kwargs): return JsonResponse({ 'msg': 'view post ok' }) ----------------------------------------------- from rest_framework.views import APIView from rest_framework.response import Response class BookAPIView(APIView): def get(self, request, *args, **kwargs): return Response({ 'msg': 'apiview get ok' }) def post(self, request, *args, **kwargs): return Response({ 'msg': 'apiview post ok' }) settings文件中必定要註冊drf INSTALLED_APPS = [ 'rest_framework', ] # drf框架自定義配置 REST_FAMEWORK = { # 全局配置解析類:適用於全部視圖類 'DEFAULT_PARSER_CLASSES': [ #'rest_framework.parsers.JSONParser', #'rest_framework.parsers.FormParser', #'rest_framework.parsers.MultiPartParser' ], # 全局配置渲染類:適用於全部視圖類 'DEFAULT_RENDERER_CLASSES': [ 'rest_framework.renderers.JSONRenderer', #'rest_framework.renderers.BrowsableAPIRenderer', 上線儘可能關閉 ], # 異常模塊:異常處理函數 # 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler', 'EXCEPTION_HANDLER': 'api.exception.exception_handler', } # 在api文件夾中新建exception文件 # 必定要在settings文件中將異常模塊配置本身的異常處理函數 from rest_framework.views import exception_handler as drf_exception_handler from rest-framework.response import Rseponse def exception_handler(exc, context): response = drf_exception_handler(exc, context) detail = '%s - %s - %s' % (context.get('view'), context.get('request').method, exc) if not response: 服務器錯誤 response = Rseponse({'detail':detail}) else: response.data = {'detail':detail} # 核心:要將response.data.get('detail')信息記錄到日誌中 logger.waring(response.data.get('detail')) return response # utils文件夾下的views.py文件 def handle_exception(self,exc): """ Handle any exception that occurs, by returning an appropriate response, or re-raising the error. # 處理任何發生的異常,經過返回適當的響應, # 或從新引起錯誤。 """ # 出現三大認證相關異常,額外處理一下響應頭 if isinstance(exc, (exceptions.NotAuthenticated, exceptions.AuthenticationFailed)): # WWW-Authenticate header for 401 responses, else coerce to 403 auth_header = self.get_authenticate_header(self.request) if auth_header: exc.auth_header = auth_header else: exc.status_code = status.HTTP_403_FORBIDDEN # 獲取出來異常的函數:該文件獨立存在的exception_handler函數 exception_handler = self.get_exception_handler() # 給異常處理提供額外的參數 context = self.get_exception_handler_context() # exc異常對象,context中用視圖對象和請求對象 response = exception_handler(exc,context) # 默認的exception_handler函數只處理客戶端異常造成response對象,服務器異常不作處理,返回None if response is None: self.raise_uncaught_exception(exc) response.exception = True return response def dispatch(self, request, *args, **kwargs): self.args = args self.kwargs = kwargs # 二次封裝request對象,包含解析模塊 request = self.initialize_request(request,*args,**kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: # 三大認證(認證、權限、頻率),用來替換csrf安全認證,要比csrf認證強大得多 # 異常模塊 -處理請求異常分支的 response = self.handle_exception(exc) # 二次封裝response,處理告終果渲染 self.response = self.finalize_response(request, response, *args, **kwargs) return self.response status文件中能夠自定義網絡狀態碼