Ajax和django自帶序列化元件

Formerly0^0發表於2024-03-28

Ajax和django自帶序列化元件

1.Ajax

1.1 Ajax介紹

  • AJAX(Asynchronous Javascript And XML)翻譯成中文就是“非同步的Javascript和XML”。
    • 即使用Javascript語言與伺服器進行非同步互動,傳輸的資料為XML(當然,傳輸的資料不只是XML)。
  • AJAX 不是新的程式語言,而是一種使用現有標準的新方法。
  • AJAX 最大的優點是在不重新載入整個頁面的情況下,可以與伺服器交換資料並更新部分網頁內容。(這一特點給使用者的感受是在不知不覺中完成請求和響應過程)
  • AJAX 不需要任何瀏覽器外掛,但需要使用者允許JavaScript在瀏覽器上執行。
    • 同步互動:
      • 客戶端發出一個請求後,需要等待伺服器響應結束後,才能發出第二個請求;
    • 非同步互動:
      • 客戶端發出一個請求後,無需等待伺服器響應結束,就可以發出第二個請求。

1.2 傳送請求方式

  • 向後端傳送請求的方式
    • 瀏覽器地址直接url回車
      • GET請求
    • a標籤的 href 屬性
      • GET請求
    • form表單
      • GET請求/POST請求
    • Ajax
      • GET請求/POST請求

1.3 Ajax案例

  • 頁面上有兩個 input 框
  • 在第一個input框中輸入數字,在第二個框中也輸入數字
  • 計算結果渲染到第三個框中
1.3.1 JS實現
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div>number_one : <input type="text" id="number1"></div>
<div>number_two : <input type="text" id="number2"></div>
<div>result : <input type="text" id="result"></div>
<button id="btn_result">點我計算結果</button>
<script>
    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            let result = parseInt(numberOne) + parseInt(numberTwo)
            $("#result").val(result)
        })
    )


</script>
</body>
</html>
1.3.2 Ajax基礎實現
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<div>number_one : <input type="text" id="number1"></div>
<div>number_two : <input type="text" id="number2"></div>
<div>result : <input type="text" id="result"></div>
<button id="btn_result">點我計算結果</button>
<script>

    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            // 基於Ajax傳送請求
            $.ajax({
                // 引數 url : 指定當前資料提交的網址,如果不寫 form表單的action是一樣,預設釋放前路由地址
                url: "",
                // type : 請求型別 GET / POST  ,預設是get
                type: "post",
                // data : 自己攜帶資料 ,做成字典的格式傳輸資料
                data: {'number_one': numberOne, "number_two": numberTwo},
                // success : 回撥函式 , 負責接收到後端返回的資料
                success: function (data) {
                    console.log(data)
                    $("#result").val(data)
                }
            })
        })
    )


</script>
</body>
</html>
1.3.3 渲染json 資料
  • 基於前端的js轉換資料型別
def home(request):
    if request.method == "POST":
        data = request.POST
        number_one = data.get("number_one")
        number_two = data.get("number_two")
        result = int(number_one) + int(number_two)
        # return HttpResponse(result)
        return HttpResponse(json.dumps({"code": 300, "result": result}))
    return render(request, "home.html", locals())
<script>

    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            // 基於Ajax傳送請求
            $.ajax({
                // 引數 url : 指定當前資料提交的網址,如果不寫 form表單的action是一樣,預設釋放前路由地址
                url: "",
                // type : 請求型別 GET / POST  ,預設是get
                type: "post",
                // data : 自己攜帶資料 ,做成字典的格式傳輸資料
                data: {'number_one': numberOne, "number_two": numberTwo},
                // success : 回撥函式 , 負責接收到後端返回的資料
                success: function (data) {
                    console.log(data)
                    console.log(typeof (data))
                    // 使用 js自己的序列化方法序列化資料
                    let dataVal = JSON.parse(data)
                    console.log(typeof (dataVal))
                    if (dataVal.code === 200) {
                        $("#result").val(dataVal.result)
                    } else {
                        alert("非法的資料")
                    }
                }
            })
        })
    )


</script>
  • 上述方法,後端傳給前端的資料是 string 型別,需要在前端自己做一步型別強轉
  • 後端的 jsonresponse物件渲染json格式的資料
  • 發現在前端接收到的資料型別就是 object 型別,不需要額外的轉換
def home(request):
    if request.method == "POST":
        data = request.POST
        number_one = data.get("number_one")
        number_two = data.get("number_two")
        result = int(number_one) + int(number_two)
        return JsonResponse({"code": 300, "result": result})
    return render(request, "home.html", locals())
<script>

    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            // 基於Ajax傳送請求
            $.ajax({
                // 引數 url : 指定當前資料提交的網址,如果不寫 form表單的action是一樣,預設釋放前路由地址
                url: "",
                // type : 請求型別 GET / POST  ,預設是get
                type: "post",
                // data : 自己攜帶資料 ,做成字典的格式傳輸資料
                data: {'number_one': numberOne, "number_two": numberTwo},
                // success : 回撥函式 , 負責接收到後端返回的資料
                success: function (data) {
                    console.log(data)
                    console.log(typeof (data))
                    // 使用 js自己的序列化方法序列化資料
                    {#let dataVal = JSON.parse(data)#}
                    console.log(typeof (data))
                    if (data.code === 200) {
                        $("#result").val(data.result)
                    } else {
                        alert("非法的資料")
                    }
                }
            })
        })
    )
</script>

1.4 Ajax語法總結

<script>
    // 先給按鈕繫結點選事件
    $('#btn').click(function () {
        // 向後端傳送Ajax請求
        $.ajax({
            // (1)指定傳送後端的請求介面
            url: '',// 不寫就是朝當前地址傳送請求
            
            // (2)請求方式
            type: "post", // 不指定預設就是 get 全小寫
          
            // dataType 引數應該是一個字串,表示期望從伺服器返回的資料型別(如 "json", "xml", "script", "html" 等)
            // dataType: "json",
          
            // (3)提交資料, 自己攜帶資料 ,做成字典的格式傳輸資料
            data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},
            
            // (4)非同步提交有一個回撥函式 (非同步回撥機制)
            // 當後端返回結果的時候會自動觸發,args 會自動接受後端傳過來的結果
            success: function (args) {
                {#alert(args)#}
                // 透過DOM操作動態資料渲染到第三個 input 框中
                console.log(args) // string
                $('#d3').val(args)
            },
        })
    })
</script>

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

  • 無論是form表單還是Ajax,傳輸資料的預設編碼格式都是urlencoded
    • 只能傳輸鍵值對,無法傳輸檔案資料
  • formdata : 可以傳輸檔案資料 request.FILES
  • json : application/json
def home(request):
    if request.method == "POST":
        data =request.body
        print(data) # b'{"number_one":"32","number_two":"3"}'
        data = data.decode('utf8')
        print(data) # {"number_one":"32","number_two":"3"}
        print(type(data)) # <class 'str'>
        data = json.loads(data)
        print(type(data))
        number_one = data.get("number_one")
        number_two = data.get("number_two")
        result = int(number_one) + int(number_two)
        return JsonResponse({"code": 200, "result": result})
    return render(request, "home.html", locals())
<script>

    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            // 基於Ajax傳送請求
            $.ajax({
                // 引數 url : 指定當前資料提交的網址,如果不寫 form表單的action是一樣,預設釋放前路由地址
                url: "",
                // type : 請求型別 GET / POST  ,預設是get
                type: "post",
                // data : 自己攜帶資料 ,做成字典的格式傳輸資料
                data: JSON.stringify({'number_one': numberOne, "number_two": numberTwo}),
                {#data: {'number_one': numberOne, "number_two": numberTwo},#}
                // success : 回撥函式 , 負責接收到後端返回的資料
                success: function (data) {
                    console.log(data)
                    console.log(typeof (data))
                    // 使用 js自己的序列化方法序列化資料
                    {#let dataVal = JSON.parse(data)#}
                    console.log(typeof (data))
                    if (data.code === 200) {
                        $("#result").val(data.result)
                    } else {
                        alert("非法的資料")
                    }
                }
            })
        })
    )


</script>

1.6 Ajax傳輸檔案資料

<script>

    $(document).ready(
        $("#btn_result").click(function () {
            let numberOne = $("#number1").val();
            let numberTwo = $("#number2").val();
            let fileVal = $("#file_input")[0].files[0];
            // Ajax攜帶檔案資料需要藉助第三方的 formData物件
            // (1)例項化得到一個 form物件
            // 將所有的鍵值對資料都要放到 form物件中
            let formDataObj = new FormData();
            formDataObj.append("numberOne", numberOne)
            formDataObj.append("numberTwo", numberTwo)
            formDataObj.append("file", fileVal)
            console.log(fileVal)
            console.log(formDataObj)
            // 基於Ajax傳送請求
            $.ajax({
                // 引數 url : 指定當前資料提交的網址,如果不寫 form表單的action是一樣,預設釋放前路由地址
                url: "",
                // type : 請求型別 GET / POST  ,預設是get
                type: "post",
                // data : 自己攜帶資料 ,做成字典的格式傳輸資料
                // (2)傳輸的data直接放上面的 form物件即可
                data: formDataObj,
                // (3)走form物件不能讓他使用編碼對資料進行編碼
                contentType: false, // 預設編碼是 urlencoded
                // (4)告訴瀏覽器不要對資料進行額外的處理
                processData: false,
                {#data: {'number_one': numberOne, "number_two": numberTwo},#}
                // success : 回撥函式 , 負責接收到後端返回的資料
                success: function (data) {
                    console.log(data)
                    console.log(typeof (data))
                    // 使用 js自己的序列化方法序列化資料
                    {#let dataVal = JSON.parse(data)#}
                    console.log(typeof (data))
                    if (data.code === 200) {
                        $("#result").val(data.result)
                    } else {
                        alert("非法的資料")
                    }
                }
            })
        })
    )
</script>

def home(request):
    if request.method == "POST":
        # 可以用來判斷當前的請求方式是否是Ajax
        print(request.is_ajax()) # True
        # print(type(request.body.decode("utf-8")[0]))
        # 獲取普通的鍵值對資料只需要透過 POST方法
        data = request.POST
        print(data)  # <QueryDict: {'numberOne': ['2'], 'numberTwo': ['2']}>
        # 獲取form物件中的檔案資料也要藉助 FILES
        print(request.FILES)  # <MultiValueDict: {'file': [<InMemoryUploadedFile: avatar.jpg (image/jpeg)>]}>
        return JsonResponse({"code": 200, "result": "ok"})
    return render(request, "home.html", locals())

2. django自帶的序列化元件

2.1 基於jsonresponse序列化資料

from app01.models import User
def get_user(request):
    # 查詢所有使用者資料
    user_data_list = []
    user_queryset = User.objects.all()
    for user_obj in user_queryset:
        user_data_list.append(
            {
                "username": user_obj.username,
                "age": user_obj.age,
                "gender": user_obj.get_gender_display()
            }
        )
    print(user_data_list)
    return JsonResponse(user_data_list, safe=False)
  • 前端顯示js格式的資料
[
{
"username": "serein",
"age": 18,
"gender": "female"
},
{
"username": "zzp",
"age": 28,
"gender": 2
},
{
"username": "xyk",
"age": 22,
"gender": "female"
}
]

2.2 基於Django自帶的serializers

# 使用內建的serializers
def get_user(request):
    # 查詢所有使用者資料
    user_queryset = User.objects.all()
    user_data_list = serializers.serialize('json', user_queryset)
    # format引數如下,
    # BUILTIN_SERIALIZERS = {
    #     "xml": "django.core.serializers.xml_serializer",
    #     "python": "django.core.serializers.python",
    #     "json": "django.core.serializers.json",
    #     "yaml": "django.core.serializers.pyyaml",
    #     "jsonl": "django.core.serializers.jsonl",
    # }
    print(user_data_list)
    return JsonResponse(user_data_list, safe=False)

  • 前端展示
"[{\"model\": \"app01.user\", \"pk\": 1, \"fields\": {\"username\": \"serein\", \"age\": 18, \"gender\": 1}}, {\"model\": \"app01.user\", \"pk\": 2, \"fields\": {\"username\": \"zzp\", \"age\": 28, \"gender\": 2}}, {\"model\": \"app01.user\", \"pk\": 3, \"fields\": {\"username\": \"xyk\", \"age\": 22, \"gender\": 1}}]"

相關文章