1. 程式人生 > 實用技巧 >Ajax基本使用和JsonHttpResponse

Ajax基本使用和JsonHttpResponse

Ajax :非同步請求,不會重新整理頁面,頁面上使用者之前輸入的資料都不會丟失。

簡單請求案例:

views頁面

from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
def login(request):
    if request.method == "POST":
        if request.POST.get("uname") == "root":
            return HttpResponse("ok")
        return
HttpResponse("error") return render(request, "login.html") def home(request): return render(request,"home.html")

HTML頁面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div> <label> 使用者名稱: <input type="text" name="username" id="username"> </label> <label> 密碼: <input type="password" name="password" id="password"> </label> <button id="btn">提交</button> <span style="color: red;font-size: 12px"
id="err"></span> </div> </body> <script src="{% static 'js/jquery.js' %}"></script> <script> $('#btn').click(function (){ var name = $('#username').val(); var pwd = $('#password').val(); console.log(name,pwd) $.ajax({ url: {% url 'login' %}', type: 'post', data: {uname:name,upwd:pwd}, success: function (res) { console.log(res, typeof res) if(res==="ok"){ location.href = '{% url 'home' %}'; } else{$('#err').text("使用者名稱或者密碼錯誤") } } }) }) </script> </html>

注意點:

$.ajax({  //
  url:'/login_ajax/',  //寫路徑時,如果後臺使用的是django框架,那麼url路徑的後面的斜槓要加上,如果想不加上斜槓,
那麼需要在django的settings配置檔案中加上 APPEND_SLASH = False,並且後臺的urls.py檔案中的路徑要和ajax請求路徑對應好,
該有斜槓寫斜槓,不需要斜槓的,去掉斜槓 type:'post', ... }),

在js程式碼中客戶使用url別名反向解析來寫路徑:

$.ajax({  //
  url:'{% url "login_ajax" %}',
  type:'post',
  ...
}),
但是,要注意一點,當這段js程式碼是寫到某個js檔案中,然後hmtl檔案通過script標籤的src屬性來引入時,
{% url "login_ajax" %}語法就不能被模板渲染了,也就是失效了

響應字典資料型別

方式一:手動利用json序列化和反序列化

views頁面

from django.shortcuts import render,HttpResponse,redirect
from django.urls import reverse
from django.http import JsonResponse
def login(request):
    if request.method == "POST":
        if request.POST.get("uname") == "root":
            return HttpResponse("ok")
        return HttpResponse("error")
    return render(request, "login.html")

def home(request):
    return render(request,"home.html")

def data(request):
    import json
    dic = {"summer":["夏日驚喜","西瓜","哈密瓜","涼麵"]}
    dic_str = json.dumps(dic,ensure_ascii=False)
    return HttpResponse(dic_str)

HTML頁面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>這是home頁面</h1>
<button id="btn_home">點選有驚喜</button>
<ul>

</ul>
</body>
<script src="{% static 'js/jquery.js' %}"></script>
<script>
    $('#btn_home').click(function () {
        $.ajax({
            url: '{% url "data" %}',
            type: 'get',
            success: function (res) {
                console.log(res, typeof res) // 夏天 string  用HttpResponce傳遞字典資料, 只能取到字典的鍵
                // 引入json模組後得到字串形式的字典: {"summer": ["西瓜", "哈密瓜", "涼麵"]} string
                var dic_res = JSON.parse(res)
                console.log(dic_res,typeof dic_res)
                var ret = dic_res.summer
                // 將列表中的內容放到頁面中
                for (var i=0;i<ret.length;i++){
                   var content = ret[i];
                    var liEle = document.createElement('li');
                    liEle.innerText = content
                    $('ul').append(liEle);

                }
            }
        })
    })
</script>

</html>


# 第一種方式,直接通過HttpResponse回覆字典資料,那麼ajax接受到資料之後,需要自行反序列化
# data_list_str = json.dumps(data_list, ensure_ascii=False)
# 直接使用HttpResponse回覆字典型別資料,那麼會將字典裡面元素的鍵都拼接成一個字串來響應,所以不是我們想要的結果,所以我們先將字典型別資料,轉換成json字串,在通過HttpResponse來進行響應

方式二:手動加響應頭鍵值對['content-type'] = 'application/json'

# data函式改寫
def data(request):
    import json
    dic = {"summer":["夏日驚喜","西瓜","哈密瓜","涼麵"]}
    dic_str = json.dumps(dic,ensure_ascii=False)
    ret = HttpResponse(dic_str)
    ret['content-type'] = 'application/json'
    return ret


# HTML接收和顯示資料修改
success: function (res) {
                console.log(res, typeof res) // 夏天 string  用HttpResponce傳遞字典資料, 只能取到字典的鍵
                // 引入json模組後得到字串形式的字典: {"summer": ["西瓜", "哈密瓜", "涼麵"]} string
                {#var dic_res = JSON.parse(res)#}
                {#console.log(dic_res,typeof dic_res)#}
                var ret = res.summer
                // 將列表中的內容放到頁面中
                for (var i=0;i<ret.length;i++){
                   var content = ret[i];
                    var liEle = document.createElement('li');
                    liEle.innerText = content
                    $('ul').append(liEle);


#第二種方式:通過HttpResponse回覆字典資料,回覆之前,加上一個響應頭鍵值對,如下,那麼ajax收到這個響應資料的時候,
會檢視這個響應頭,發現content-type這個響應頭的值為application/json,那麼會自動對響應資料進行反序列化,不需要我們自己手動反序列化了

方式三:引入JsonHttpResponce

# data部分
from django.http import JsonResponse
def data(request):
    import json
    dic = {"summer":["夏日驚喜","西瓜","哈密瓜","涼麵"]}
    # dic_str = json.dumps(dic,ensure_ascii=False)
    # ret = HttpResponse(dic_str)
    # ret['content-type'] = 'application/json'
    return JsonResponse(dic)
#JsonResponse:1 序列化資料 2 加上['content-type'] = 'application/json'這個響應頭鍵值對

注意:

lst = ["夏日驚喜","西瓜","哈密瓜","涼麵"]
    #當使用JsonResponse回覆非字典型別資料時,需要將safe引數的值改為False, 不然會報錯
    return JsonResponse(lst, safe=False)

區域性更新資料案例:

views頁面

def sub(request):
    if request.method == "GET":
        return render(request,"sub.html")
    else:
        import json
        print(request.body)
        data = request.body.decode()
        print(data)
        data = json.loads(data)
        print(data)
        a = int(data["a"])
        b = int(data["b"])
        ret = a+b
        print(ret)
        return HttpResponse(ret)

HTML頁面

{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<label>
    a: <input type="text" name="a" id="aid">
</label>
<label>
    b: <input type="text" name="b" id="bid">
</label>
<button id="btn_sub">查詢</button>
<br>
a+b= <span id="sp" style="color: burlywood"></span>

</body>
<script src="{% static 'js/jquery.js' %}"></script>
<script>

    $('#btn_sub').click(function () {
        var a = $('#aid').val();
        var b = $('#bid').val();
        $.ajax({
            url: '{% url 'sub' %}',
            type: 'post',
            headers: {
                'Content-Type':'application/json',
            },
            data: JSON.stringify({a:a,b:b}),
            success: function (res) {
                {#alert(res);#}
                $('#sp').text(res)
            }
        })
    })
</script>
</html>

請求頭訊息格式分析

請求訊息格式和請求方法沒有關係,和請求頭鍵值對中的這一組鍵值對有關係

file說明    <!-- enctype="multipart/form-data"這個引數就是將本次請求的訊息格式,也就是那個content-type的值改為multipart/form-data,
那麼本次http請求,會將檔案資料片段傳送 -->

Content-Type: application/x-www-form-urlencoded; //瀏覽器傳送資料ajax或者form表單,預設的格式都是它 它表示請求攜帶的資料格式,application/x-www-form-urlencoded對應的資料格式是:a=1&b=2
'''
socket 接收到我們請求資料,會分析一下Content-Type: application/x-www-form-urlencoded;這個請求頭

# 叫做解析器
if Content-Type == 'application/x-www-form-urlencoded':
data = 'a=1&b=2'
l1 = data.split('&') [a=1,b=2]
for i in l1:
k,v = i.split('=')
if 請求方法 == 'GET':
request.GET[k] = v

elif Content-Type == 'multipart-formdata':
request.FILES

#django沒有內建對appcation/json的訊息格式的解析器,所以如果請求資料是json型別,那麼我們需要自行解析

'''