Django Rest Framework -解析器

基本代碼結構

urls.py前端

rom django.conf.urls import url, include
from web.views.s5_parser import TestView
 
urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

views.pypython

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser
 
 
class TestView(APIView):
    # JSONParser:請求頭content-type爲application/json
    # FormParser:請求頭content-type爲application/x-www-form-urlencoded
    # MultiPartParser: 請求頭content-type爲multipart/form-data
    #  FileUploadParser:上傳文件
    parser_classes = [JSONParser, FormParser, MultiPartParser, FileUploadParser, ]
 
    def post(self, request, *args, **kwargs):
        print(request.content_type)
 
        # 獲取請求的值,並使用對應的JSONParser進行處理
        print(request.data)
 
        # application/x-www-form-urlencoded 或 multipart/form-data時,request.POST中才有值
        print(request.POST)
        print(request.FILES)
 
        return Response('POST請求,響應內容')
 
    def put(self, request, *args, **kwargs):
        return Response('PUT請求,響應內容')

  parser_classes屬性變量中的值,是各類解析器對象。前端會向後臺發送不一樣類型的請求,而django後臺的drf接口必須經過配置解析器才能獲取到相關請求數據。經常使用的解析器主要是「JSONParser」和「FormParser」這兩個解析器。web

源碼分析

1.爲何使用parser_classes屬性變量,它有什麼用?django

 

一樣仍是從APIView類的入口方法dispatch入口,在dispatch方法中,調用了initialize_request方法。這個方法在前文中已經說過,是用來封裝django原生的request請求的。由上圖知道,django原生的request請求數據被封裝到了Request對象中,在實例化該對象時,將解析數據的解析器初始化到了parsers屬性變量中。跳轉到get_parsers方法中,能夠看到,一樣也是返回的是列表生成式。json

再跳轉回APIView類中,能夠看到屬性變量parser_classes定義的地方。一樣也能夠經過settings配置文件進行全局配置。若是不須要進行全局配置,那就要在自定義的視圖類中對parser_classes屬性變量進行從新賦值,即:「parser_classes = [JSONParser, FormParser, MultiPartParser, FileUploadParser,]」。這列表元素都是解析器對象,只要這樣配置好,drf就會根據parser_classes中的解析器去解析數據。app

 2.爲何從request.data中獲取數據?框架

看到這裏,心中有了疑惑,Django Rest Framework框架是在那裏觸發解析器這個功能的,在上面的源碼分析中並未調用任何一個關於解析相關功能的方法,只是作了一個讀取配置文件,封裝新的request對象的過程,因此是在咱們須要讀數據的時候纔會去觸發解析器這個功能,因此咱們從request.data入手,咱們知道,django原生的request請求,會被drf經過Request對象封裝,那麼就跳轉到Request類定義中看看這個「data」的實現。在data方法的實現中能夠看到前端請求的數據是經過「_load_data_and_files」方法獲取的,而且返回值是「_full_data」屬性變量。先跳轉到「_load_data_and_files」方法中:源碼分析

 

在「_load_data_and_files」方法中可知,是經過調用「_parse」方法去獲取請求數據的,而且將請求數據保存在「_data」和「_files」屬性變量中。除文件相關的數據外的數據都保存在了「_data」中,而「_data」中的數據又都賦值到「_full_data」屬性變量中。又由上一張圖可知,「data」方法的返回值是「_full_data」,即:data方法獲取到的數據就是「_full_data」中的數據。post

  

如今進一步分析_parse,首先第一步作的是獲取請求頭,能夠看到將獲取到的請求頭保存到了「media_type」變量中。而後又經過調用「select_parser(self, self.parsers)」方法,來選擇所須要的解析器(參數「self.parsers」就是咱們在自定義視圖中「parser_classes」的值)。url

  

又經過,parser_classes中解析器對象中的parser方法來解析請求到的數據,即:「parsed = parser.parse(steam, media_type, self.parser_context)」。這裏以「JSONParser」對象爲例,由上圖可知,media_type屬性變量中保存的是該解析器所對應的請求頭,self.parser_context中,保存的是從前端請求中獲取到的請求頭。

  再來到「JSONParser」類的「parse」方法中可知,再經過返回「json.load」來處理請求數據。返回的請求數據就會保存到「Request」類的「_parse」方法中的parsed變量中。而_parse方法的返回值爲元組,第一個元素就是須要的數據。這些數據會在「_load_data_and_files」方法中,賦值給「Request」類的「_data」屬性方法,而_data中的數據會賦值給「_full_data」中。所以,「Request」類中「data」方法返回值是「_full_data」,這樣,就能夠經過「request.data」獲取請求數據。

全局配置

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]
}

  配置加入不一樣的解析器,就會解析不一樣類型的請求數據,固然是能夠同時配置加入多個解析器的。一樣的,配置了全局解析器後,那麼,在自定義的視圖類中,就能夠不用經過「parser_classes」屬性變量進行添加解析器的。

相關文章
相關標籤/搜索