解析器

前提:django 的 request.POST 有值

  • 請求頭要求:若是請求頭中的 Content-Typeapplication/x-www-form-urlencoded ,纔去 request.body 中解析數據
  • 數據格式要求:name=xi&age=18

form 表單提交默認會按照上面的兩種要求進行提交python

ajax 提交中的 data 數據雖然是字典格式,但默認也會把字典轉換成上面的數據格式再帶上請求頭進行提交ajax

若是 ajax 提交中指定 headers 爲 {'Content-Type': 'application/json'},那麼 body 有值,POST 無值django

若是 ajax 提交中指定 headers 爲 {'Content-Type': 'application/json'},且 data 的數據格式指定爲 JSON.stringfy(),那麼 body 有值,POST 無值,可是能夠到 request.body 中拿到 json 數據,轉成字符串類型,而後 json.loads(request.body) 便可獲取到字典類型的數據json

rest framework 解析器

依靠請求頭 content-type 對用戶請求體中的數據進行解析,解析到 request.data api

# demo\api\urls

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
]
# demo\api\views

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

    def post(self, request, *args, **kwargs):
        '''
        容許用戶發送JSON格式數據
            a. content-type: application/json
            b. {'name':'xi', 'age':18}
        '''
        # 獲取解析後的結果,用的時候纔去解析,因此是代碼的起始位置
        '''
        1. 獲取用戶的請求
        2. 獲取用戶的請求體
        3. 根據用戶請求頭和 parser_classes = [JSONParser, FormParser, ]中支持的請求頭進行比較
        4. JSONParser對象去請求體
        5. 賦值給 request.data 做爲處理後的結果
        '''
        print(request.data)
        
        return HttpResponse("ParserView")

源碼流程

經過 Request 找到 datadata 中有 _load_data_and_files() ,裏面調用了 self._parse()self._parse() 中有 self.content_type瀏覽器

圖片中 344 行,select_parser() 是選擇解析器,根據上面用戶提交的請求頭和所傳的 self.parsers 來找,parsers 就是前面 views.py 中所設置的 parser_classes = [JSONParser, FormParser, ]self 是請求相關的全部數據,即請求對象,它裏面有一個 contype_type ,是當前用戶的 content_type 。根據這兩個參數進行選擇服務器

選擇好解析器,執行解析器的 parse() 方法,若是選擇的是 JSONParser 解析器,就到 JSONParserparse() 方法app

JSONParser 中執行 json.load() 方法,將 json 數據變爲字典類型post

上面的內容爲源碼的一部分,實際上流程的入口其實仍是從 dispatch 出發,對 request 進行封裝this

def get_parsers(self):
    """
    Instantiates and returns the list of parsers that this view can use.
    """
    # self.parser_classes 讀取的仍是 APIView 中的設置
    return [parser() for parser in self.parser_classes]

因此請求剛進來時,全部 views.py 中所設置的 parser_classes = [JSONParser, FormParser, ] 解析器所有實例化成對象,也封裝到 request 中了。目前所學,Request 中有三種東西:封裝的 request、認證的全部對象、解析器的全部對象,一樣,解析器也能夠進行全局配置

# demo\demo\settings.py

REST_FRAMEWORK = {
    "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
    "DEFAULT_VERSION": 'v1',
    "ALLOWED_VERSION": ['v1', 'v2'],
    "VERSION_PARAM": 'version',
    "DEFAULT_PARSER_CLASSES": ["rest_framework.parsers.JSONParser", "rest_framework.parsers.FormParser"]
}
# demo\api\views.py

class ParserView(APIView):

    def post(self, request, *args, **kwargs):
        '''
        容許用戶發送JSON格式數據
            a. content-type: application/json
            b. {'name':'xi', 'age':18}
        '''
        # 獲取解析後的結果
        print(request.data)
        return HttpResponse("ParserView")

總結

  • 使用
    • 全局配置
    • request.data
  • 源碼流程
    • dispatch:request 封裝
    • request.data
  • 常見的請求頭
    • Referer:瀏覽器向 Web 服務器代表本身是從哪一個網頁的 URL 得到點擊當前請求中的網址
    • User-Agent:瀏覽器代表本身的身份(是哪一種瀏覽器)
    • Host:客戶端指定本身想訪問的 Web 服務器的 IP 地址和端口號
    • Accept:告訴 Web 服務器本身接受什麼介質類型,*/* 表示任何類型,type/* 表示該類型下的全部子類型
  • 常見的狀態碼
  • 請求方法
相關文章
相關標籤/搜索