Django-請求消息之請求頭中的contentType

引言:

咱們知道,HTTP 協議是以 ASCII 碼傳輸,創建在 TCP/IP 協議之上的應用層規範。規範把 HTTP 請求分爲三個部分:狀態行、請求頭、消息主體。相似於下面這樣:
<method> <request-url> <version>
<headers>

<entity-body></entity-body></headers></version></request-url></method>
協議規定 POST 提交的數據必須放在消息主體(entity-body)中,但協議並無規定數據必須使用什麼編碼方式。實際上,開發者徹底能夠本身決定消息主體的格式,只要最後發送的 HTTP 請求知足上面的格式就能夠。

可是,數據發送出去,還要服務端解析成功纔有意義。通常服務端語言如 php、python 等,以及它們的 framework,都內置了自動解析常見數據格式的功能。服務端一般是根據請求頭(headers)中的 Content-Type 字段來獲知請求中的消息主體是用何種方式編碼,再對主體進行解析。因此說到 POST 提交數據方案,包含了 Content-Type 和消息主體編碼方式兩部分。下面就正式開始介紹它們。php

一:contentType常見的提交數據的方式

1:application/x-www-form-urlencoded

1.1介紹

這應該是最多見的 POST 提交數據的方式了。瀏覽器的原生 form 表單,若是不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交數據。請求相似於下面這樣(無關的請求頭在本文中都省略掉了):

html

POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8

title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3


首先,Content-Type 被指定爲 application/x-www-form-urlencoded;其次,提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支持。例如 PHP 中,$_POST['title'] 能夠獲取到 title 的值,$_POST['sub'] 能夠獲得 sub 數組。

不少時候,咱們用 Ajax 提交數據時,也是使用這種方式。例如 JQuery 和 QWrap 的 Ajax,Content-Type 默認值都是「application/x-www-form-urlencoded;charset=utf-8」。python

1.2對於這種數據封裝格式,Django服務端如何處理的

request.GET
request.POST
對於application/x-www-form-urlencoded封裝格式,Django經過上面兩種方式就能夠獲取數據,中間複雜的過程都已經被Django處理了

  

 

2:multipart/form-data

 2.1:數據類型的介紹

這又是一個常見的 POST 數據提交的方式。咱們使用表單上傳文件時,必須讓 form 的 enctyped 等於這個值。直接來看一個請求示例:

ajax

POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="text"

title
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png

PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--


這個例子稍微複雜點。首先生成了一個 boundary 用於分割不一樣的字段,爲了不與正文內容重複,boundary 很長很複雜。而後 Content-Type 裏指明瞭數據是以 mutipart/form-data 來編碼,本次請求的 boundary 是什麼內容。消息主體裏按照字段個數又分爲多個結構相似的部分,每部分都是以 --boundary 開始,緊接着內容描述信息,而後是回車,最後是字段具體內容(文本或二進制)。若是傳輸的是文件,還要包含文件名和文件類型信息。消息主體最後以 --boundary-- 標示結束。關於 mutipart/form-data 的詳細定義,請前往 rfc1867 查看。

這種方式通常用來上傳文件,各大服務端語言對它也有着良好的支持。

上面提到的這兩種 POST 數據的方式,都是瀏覽器原生支持的,並且現階段原生 form 表單也只支持這兩種方式。可是隨着愈來愈多的 Web 站點,尤爲是 WebApp,所有使用 Ajax 進行數據交互以後,咱們徹底能夠定義新的數據提交方式,給開發帶來更多便利。chrome

2.2:上傳文件

 參考博文:Django-multipart/form-data數據封裝類型---文件上傳json

 

3:application/json  (python開發處理最多的)

3.1:json數據類型介紹

application/json 這個 Content-Type 做爲響應頭你們確定不陌生。實際上,如今愈來愈多的人把它做爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。

JSON 格式支持比鍵值對複雜得多的結構化數據,這一點也頗有用數組

form表單是不能發送json數據類型的,而ajax卻可以發送幾乎任何數據類型瀏覽器

如何使用ajax發送json請求數據呢?app

3.2:案例1:瀏覽器客戶端利用ajax發送json數據

html文件----客戶端

<h4>2 攜帶參數的AJax</h4>
{% csrf_token %}
<input type="text" id="num1"> + <input id="num2" type="text"> = <input id="ret" type="text"><button class="cal">計算</button>

<script>
           $(".cal").click(function () {

           var num1=$("#num1").val();
           var num2=$("#num2").val();

           $.ajax({
               url:"/cal/",
               type:"post",
               contentType:"json",      //封裝類型
               data:JSON.stringify({  //序列化                    num1:num1,
                   num2:num2,
                   //csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val()
               }),
               success:function (response) {
                   console.log(response);
                   $("#ret").val(response)
               }
           })
       })
</script>

 

Django-ORM服務端視圖函數:

def cal(request):
    import json           #bytes------》str
    json_dict=json.loads(request.body.decode("utf8"))   #反序列化
    print(json_dict["num1"]) # 213
    return HttpResponse("OK")

 

 

Django服務端解析數據類型的原理

Django解析: (僞代碼)
       if contentType:"urlencoded":  ##json數據這種方式獲取不了數據,Django是不給json解析的,那麼咱們怎麼辦?咱們能夠獲取到數據,本身解   ----request.body:解出的數據是字節格式,相似b'num1=12&num2=23'
        request.POST=data (data就是請求消息) 
    elif contentType=="formdata":
      request.FILES=data
    else: request.POST={} 空的字典queryset

 

 

 

 

4:text/xml

 XML-RPC(XML Remote Procedure Call)。它是一種使用 HTTP 做爲傳輸協議,XML 做爲編碼方式的遠程調用規範。典型的 XML-RPC 請求是這樣的:函數

POST http://www.example.com HTTP/1.1
Content-Type: text/xml

<!--?xml version="1.0"?-->
<methodcall>
    <methodname>examples.getStateName</methodname>
    <params>
        <param>
            <value><i4>41</i4></value>
         
    </params>
</methodcall>

XML-RPC 協議簡單、功可以用,各類語言的實現都有。它的使用也很普遍,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服務等等。JavaScript 中,也有現成的庫支持以這種方式進行數據交互,能很好的支持已有的 XML-RPC 服務。不過,我我的以爲 XML 結構仍是過於臃腫,通常場景用 JSON 會更靈活方便。

相關文章
相關標籤/搜索