1. 程式人生 > 其它 >Ajax 傳送json格式資料以及傳送檔案(FormData)和自帶的序列化元件: serializers

Ajax 傳送json格式資料以及傳送檔案(FormData)和自帶的序列化元件: serializers

前後端傳輸資料的編碼格式(contentType)

get請求資料就是直接放在url?後面的

url?usernmae=junjie&password=123...

可以向後端傳送post請求的方式

  • form請求
  • ajax請求

前後端傳輸資料的編碼格式

  • urlencoded
  • formdata
  • json

研究form表單:預設的資料編碼格式是(urlencoded)

結論:Django針對urlencoded編碼格式的資料會自動幫你解析封裝到request.POST中。

那麼檔案是什麼資料型別?

結論:如果將編碼格式改為form-data,那麼針對普通的鍵值對還是解析到request.POST,但是針對檔案型別格式解析到request.FILES中。

Django進行了二次封裝,後端針對不同的編碼格式在後端內部做不同的編碼解析,並放到不同的方法中。

form表單只能傳送urlencoded以及formdata兩種編碼格式。

那麼Ajax是什麼資料格式?

結論:預設也是urlencoded,資料格式username=junjie&age=20。所有後端需要request.POST接受資料

ajax傳送JSON格式資料

前後端傳輸資料的時候一定要確保編碼格式與資料真正的格式是一致的。

JSON.stringify 前端將資料轉為JSON格式 與 contentType:'application/json' 指定字元編碼格式

<script>
    $('#d1').click(function(){ // button按鈕觸發點選事件
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'username':'junjie','age':18}),//資料也需要轉為JSON格式。
            contentType:'application/json',//指定字元編碼格式
            success:function (){

            }
        })
    })
</script>

在前後端傳輸資料的編碼格式(contentType)中推導request.POST只能接收username=junjie&age=18這類的格式,那麼是否可以推導前端返回JSON在reuqest.POST中肯定無法找到。

程式碼驗證:

def ab_ajax(request):
    print(request.POST)
    return render(request,'ab_ajax.html')

補充:如何判斷當前請求是否為ajax請求?

request.is_ajax() # 判斷當前請求是否是ajax請求,返回布林值。

現在想想前後端資料互動,基於網路傳輸時,是什麼格式?

二級制格式。

def ab_ajax(request):
    if request.is_ajax():
        # print(request.is_ajax())
        print(request.body) # b'{"username":"junjie","age":18}'
    return render(request, 'ab_ajax.html')

後端拿到二進位制格式的JSON格式字串。Django針對json格式資料後端需要手動處理。

後端如何處理json格式字串

import json
def ab_ajax(request):
    if request.is_ajax():
        # print(request.is_ajax())
        # print(request.body)
        # json_bytes = request.body  # 獲取到前端傳送過來的二進位制json格式資料
        # json_str = json_bytes.decode('utf8') # 解碼,utf8格式
        # json_loads = json.loads(json_str) # 反序列化至資料初始格式
        # print(json_loads) # {'username': 'junjie', 'age': 18}
        
        json_bytes = request.body
        json_dict = json.loads(json_bytes)
				print(json_dict) # {'username': 'junjie', 'age': 18}
        # json.loads括號內如果傳入一個二進位制資料,內部會自動解碼再返序列化
    return render(request, 'ab_ajax.html')

總結,ajax傳送json格式資料需要注意的點:

  • contentType 引數 指定成 : application/json
  • 資料必須是真正的json格式資料
  • Django後端不會處理json格式資料,需要到request.body獲取並處理

Ajax傳送檔案

ajax傳送檔案需要藉助於js內建物件FormData

<script>
    //點選按鈕向後端傳送普通鍵值對和檔案資料
    $('#d4').click(function (){
        //1.利用FormData內建物件
        let obj = new FormData();
        //2.新增普通的鍵值對
        obj.append('username',$('#d1').val()); //val()// 取得第一個匹配元素的當前值 等同於value()
        obj.append('password',$('#d2').val());
        //3.新增檔案物件,$('#d3')取索引0,轉為原生jQuery物件即原生標籤物件,再用files[0]就獲得使用者傳的檔案物件
        obj.append('myfile',$('#d3')[0].files[0])
        //4.將物件基於ajax傳送到後端
        $.ajax({
            url:'',
            type:'post',
            data:obj, //直接將物件放在data中即可
            // ajax 傳送檔案必須指定兩個引數
            contentType:false, //告訴瀏覽器不需要帶任何編碼,Django後端能夠自動識別formdata物件,
            processData: false, //告訴瀏覽器,不要對資料進行任何處理,原封不動傳送到後端。

            success:function (args){}
        })
    })
</script>
def myfile(request):
    if request.is_ajax():
        if request.method == 'POST':
            print(request.POST)  
            # <QueryDict: {'username': ['junjie'], 'password': ['123']}>
            print(request.FILES)  
            # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 截圖2022-03-02 22.19.54.png (image/png)>]}>

    return render(request, 'myfile.html')

django後端會自動識別formdata物件,將前端返回的資料防止對應的請求中。

總結,ajax傳送檔案需要注意的點:

  • 需要利用內建物件FormData,普通鍵值對和檔案都能傳送

      obj.append('username',$('#d1').val());
    obj.append('password',$('#d2').val());
    obj.append('myfile',$('#d3')[0].files[0])
    
  • 需要指定兩個關鍵性的引數

    contentType: false
    processData: false
    
  • Django後端能夠直接識別formdata物件,並且能夠將內部的普通鍵值對自動解析並封裝到你request.POST中,檔案資料物件自動解析並封裝到reuqest.FILES中

Django自帶的序列化元件(drf做鋪墊)

藉助於模板語法前端顯示資料物件。

但是,由此前端能夠顯示使用者物件是藉助了模板語法,如果現在做一個前後端互動,前端不是Django框架, 前後端分離,那麼此時無法藉助於模板語法,就需要手擼前後端互動,前後端互動就要使用到JSON格式。

將後端資料結構構造為列表套字典[{},{},{}...],為什麼要構造成列表套字典呢?

首先資料有多個,列表套字典在後端有對應的資料,在JSONJS中也有對應的資料,恰好可以實現前後端互動,JSON可以序列化列表格式,字典格式也可以,前端JS反序列化後可以得到陣列套一個個的自定義物件,再通過for迴圈可以拿到一個個的自定義物件,再通過.點的方式就可以取值。

後端邏輯程式碼:

def gender(request):
    user_queryset = models.User.objects.all()
    user_list = []
    for i in user_queryset:
        tmp = {
            'pk':i.pk,
            'username':i.username,
            'age':i.age,
            'gender':i.get_gender_display() # models.py中性別使用了choice引數,取值方式改變了。
        }
        user_list.append(tmp)
    return JsonResponse(user_list,safe=False)

此時返回給前端的資料格式為列表套字典,字典中有一個個鍵值對 。

做前後端分離專案,後端要將資料程式碼處理並序列化到前端。

上述程式碼為手動更改資料型別為JSON,但是如果資料成百上千也要手動嗎?

模組:from django.core import serializers,自動將資料程式設計json格式字串。

from django.core import serializers


def gender(request):
    user_queryset = models.User.objects.all()
    res = serializers.serialize('json', user_queryset)
    return HttpResponse(res)

後端寫介面就是利用序列化組價渲染資料並寫一個介面文件,比如,告訴前端,gender中的數字代表什麼。