Django rest framework(5)----解析器

解析器的主要做用:對用戶請求體中的數據進行解析

解析器前戲

有時候咱們在接受前端傳送的值的時候,會存在這樣一個奇怪的現象使用request.body能夠取到值,而使用request.POST的時候去不到值,基於這樣的狀況,到底是如何形成的呢?前端

追瞭如下源碼發現  把request.body  中的值轉換成 POST 須要知足如下的兩個條件,也就是說必須知足如下兩個條件,纔可使用request.POST接受值,不然只能使用request.bodypython

1. 請求頭要求:
     Content-Type: application/x-www-form-urlencoded
     PS: 若是請求頭中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析數據)。
2. 數據格式要求:
     name=alex&age=18&gender=男

PS 以上的兩個條件缺一不可ajax

部分源碼以下json

 

 通常在那些地方默承認以使用request.POST 接受的呢app

表單提交:

a. form表單提交
    <form method...>
        input...
        
    </form>

  

ajax 提交的數據。headers content-type使用默認類型的

$.ajax({
    url:...
    type:POST,
    data:{name:alex,age=18} # 內部轉化 name=alex&age=18&gender=男
})

 

這樣的狀況是 request.body有值;request.POST無值,若是咱們須要取值的話能夠這樣作   json.loads(request.body)post

$.ajax({
    url:...
    type:POST,
    headers:{'Content-Type':"application/json"}
    data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...}
})

  

以上的狀況判斷去使用的時候,咱們須要去辨別 headers 中的請求類型,那麼有沒有一種好的方式,使一切變得簡單一些呢,固然下面直接上代碼有一個清晰的認識在來追蹤它的源碼this

restframework--解析器使用  

 

類視圖代碼以下:url

from rest_framework.parsers import JSONParser,FormParser

class ParserView(APIView):
    parser_classes = [JSONParser,FormParser,]
    """
    JSONParser:表示只能解析content-type:application/json頭
    JSONParser:表示只能解析content-type:application/x-www-form-urlencoded頭
    """

    def post(self,request,*args,**kwargs):
        """
        容許用戶發送JSON格式數據
            a. content-type: application/json
            b. {'name':'alex',age:18}
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        """
        1. 獲取用戶請求
        2. 獲取用戶請求體
        3. 根據用戶請求頭 和 parser_classes = [JSONParser,FormParser,] 中支持的請求頭進行比較
        4. JSONParser對象去請求體
        5. request.data
        """
        print(request.data)


        return HttpResponse('ParserView')

 

添加urlspa

url(r'parser/$', views.ParserView.as_view()), 

 

發送 表單的數據3d

 

後臺打印的數據以下

 

發送json類型的數據

 

後臺接受打印的數據以下

 

源碼流程

入口  dispatch 

 

def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        #對原始request進行加工,豐富了一些功能
        #Request(
        #     request,
        #     parsers=self.get_parsers(),
        #     authenticators=self.get_authenticators(),
        #     negotiator=self.get_content_negotiator(),
        #     parser_context=parser_context
        # )
        #request(原始request,[BasicAuthentications對象,])
        #獲取原生request,request._request
        #獲取認證類的對象,request.authticators
        #1.封裝request
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            #2.認證
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            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)

        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

initialize_request 獲取全部解析器

def initialize_request(self, request, *args, **kwargs):
        """
        Returns the initial request object.
        """
        parser_context = self.get_parser_context(request)

        return Request(
            request,
            parsers=self.get_parsers(),                  #獲取全部的解析器
            authenticators=self.get_authenticators(),    #[BasicAuthentication(),],把全部的認證類對象封裝到request裏面了
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )

get_parsers 獲取解析對象的列表

 def get_parsers(self):
        """
        Instantiates and returns the list of parsers that this view can use.
        """
        return [parser() for parser in self.parser_classes]

parser_classes

 

 

 一樣咱們能夠在settings裏面全局配置,咱們通常使用的就是全局的配置

 

REST_FRAMEWORK = {
    #版本
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",   
    #解析器
    "DEFAULT_PARSER_CLASSES":["rest_framework.parsers.JSONParser","rest_framework.parsers.FormParser"]
}
相關文章
相關標籤/搜索