Django REST framework之解析器

1. Django中數據的解析

Django接收請求和請求相關的數據時對請求頭和數據格式有一定的要求,首先看下對請求頭要求。只有請求頭中有 application/x-www-form-urlencoded,request.POST中才可能有值(去request.body中解析數據):

urls.py:

from django.urls import path, re_path
from . import views

urlpatterns = [
    re_path('(?P<version>[v1,v2]+)/django_request/', views.DjangoRequest.as_view()),
]

views.py:

from django.shortcuts import HttpResponse
from rest_framework.views import APIView

class DjangoRequest(APIView):
    def post(self, request, *args, **kwargs):
        from django.core.handlers.wsgi import WSGIRequest
        print(type(request._request))  # <class 'django.core.handlers.wsgi.WSGIRequest'>
        return HttpResponse()

可以看下源碼中是如何做的:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
上面說過即便帶着這個Content-Type也不一定有值,數據解析(轉換)時對數據格式也是有要求的,數據格式需要是 ?name=thanlon&age=23 這種格式。

之後遇到request.POST沒有值,可以考慮這兩個因素。

Form表單提交默認的Content-Type就是application/x-www-form-urlencoded,數據格式也是?name=thanlon&age=23。如果是Ajax提交:

$.ajax({
	url:...,
	type:POST,
	data:{'name':'thanlon','age':23}, // 內部也會轉換成?name=thanlon&age=23,再帶上Content-Type:application/x-www-form-urlencoded提交過去
})

Ajax可以定製請求頭,這種情況下request.body中有值,但是request.post中沒有值:

$.ajax({
	url:...,
	headers:{'Content-Type':'application/json'},
	type:POST,
	data:{'name':'thanlon','age':23},
})

Ajax將數據轉換爲JSON字符串傳到後臺,這種情況下request.body中有值,但是request.post中還是沒有值:

$.ajax({
	url:...,
	headers:{'Content-Type':'application/json'},
	type:post,
	data:JSON.stringfy({'name':'thanlon','age':23}), // {'name':'thanlon','age':23}
})

這種情況下request.body中是有值,可以使用 json.loads(request.body) 拿到json數據。當然,需要先把字節類型轉換爲字符串類型。

2. 內置解析類的使用

常用的內置解析類有 JSONParser和FormParser,JSONParser類可以解析請求頭中Content-Type是application/json的頭的數據,FormParser類可以解析請求中Content-Type是application/x-www-form-urlencoded的頭的數據。Content-Type是application/json時:

urls.py:

from django.urls import re_path
from . import views

urlpatterns = [
    re_path('(?P<version>[v1,v2]+)/parser/', views.ParserView.as_view()),
]

views.py:

from django.shortcuts import HttpResponse
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser

class ParserView(APIView):
    parser_classes = [JSONParser, ]

    def post(self, request, *args, **kwargs):
        """
        允許用戶發送JSON格式數據,請求頭中Content-Type是application/json,數據是{'name': 'erics'}
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        # request.data會觸發解析類進行數據的解析
        data = request.data
        print(type(data), data)  # <class 'dict'> {'name': 'erics'}
        return HttpResponse(f'{data}')

在這裏插入圖片描述
Content-Type是application/x-www-form-urlencoded時:

from django.shortcuts import HttpResponse
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser, FormParser

class ParserView(APIView):
    parser_classes = [JSONParser, FormParser,]

    def post(self, request, *args, **kwargs):
        data = request.data
        """
        1、獲取用戶請求
        2、獲取用戶請求體
        3、獲取用戶請求頭,需要與parser_classes = [JSONParser, FormParser]中支持的請求頭進行比較
        4、JSONParser、FormParser對象解析請求體
        5、解析的結果放到request.data中
        """
        print(type(data), data)  # <class 'django.http.request.QueryDict'> <QueryDict: {'name': ['erics']}>
        return HttpResponse(f'{data}')

在這裏插入圖片描述
Content-Type是multipart/form-data時,需要用到MultiPartParser解析類:
在這裏插入圖片描述
如果都不可以解析請求的數據:
在這裏插入圖片描述

配置多個請求類時,請求頭中的Content-Type與哪一個解析類匹配就使用哪個解析。

全局配置只需要在配置文件中添加解析類的路徑即可:

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':
        [
            'rest_framework.parsers.JSONParser',
            'rest_framework.parsers.FormParser',
            'rest_framework.parsers.MultiPartParser',
        ]
}
3. 內置解析類

Django REST framework內置的解析類實際上有4種,都是根據請求頭中Content-Type值的不同來對數據做不同的解析:
在這裏插入圖片描述

4. 解析源碼流程

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章