rest_framework框架的封裝特色和APIView請求生命週期

rest_framework框架的封裝特色:

import rest_framework
from rest_framework.views import APIView
from rest_framework.request import Request


在views.py中寫出合適的api類,只須要繼承rest_framework中generics中的某個類,重寫咱們須要的方法實現合適的邏輯便可

APIView請求生命週期

"""
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,處理告終果渲染
"""

原生的Django與drf比較:drf不受csrf認證限制

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文件中能夠自定義網絡狀態碼
相關文章
相關標籤/搜索