django與ajax交互

一個(gè)動(dòng)態(tài)網(wǎng)站是需要前端和后端進(jìn)行數(shù)據(jù)交互出革。

什么是Ajax

Ajax是一種用于創(chuàng)建快速動(dòng)態(tài)網(wǎng)頁的技術(shù)。Ajax 不是一種新的編程語言旨枯,而是一種用于創(chuàng)建更好更快以及交互性更強(qiáng)的Web應(yīng)用程序的技術(shù)栖榨。

  • AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)
  • 傳統(tǒng)的網(wǎng)頁(不使用 Ajax)如果需要更新內(nèi)容,必需重載整個(gè)網(wǎng)頁面。
  • AJAX 最大的優(yōu)點(diǎn)是在不重新加載整個(gè)頁面的情況下,可以與服務(wù)器交換數(shù)據(jù)并更新部分網(wǎng)頁內(nèi)容捅彻。

ajax目的:提高用戶體驗(yàn)贤旷,較少網(wǎng)絡(luò)數(shù)據(jù)的傳輸量。

Ajax工作原理

網(wǎng)頁DOM對(duì)象可以精確地對(duì)網(wǎng)頁中的部分內(nèi)容進(jìn)行操作砾脑、XML作為單純的數(shù)據(jù)存儲(chǔ)載體使得客戶端與服務(wù)器交換的只是網(wǎng)頁內(nèi)容的數(shù)據(jù)而沒有網(wǎng)頁樣式等等的附屬信息幼驶、XMLHttpRequest是與瀏覽器本身內(nèi)置的request相互獨(dú)立的與服務(wù)器交互的請(qǐng)求對(duì)象。

Ajax使用
  1. 創(chuàng)建XMLHttpRequest對(duì)象,也就是創(chuàng)建一個(gè)異步調(diào)用對(duì)象韧衣。
var xhr;
if (window.XMLHttpRequest) { //檢查瀏覽器的XMLHttpRequest屬性盅藻,如果為真則支持XMLHttpRequest
 // IE7+, Firefox, Chrome, Opera, Safari 瀏覽器執(zhí)行代碼
 xhr=new XMLHttpRequest(); 
} else {
 // IE6, IE5 瀏覽器執(zhí)行代碼
 xhr=new ActiveXObject("Microsoft.XMLHTTP"); 
}

2.向服務(wù)器發(fā)送請(qǐng)求

xhr.open(method,url,async);  
send(string);  //post請(qǐng)求時(shí)才使用字符串參數(shù)厢漩,否則不用帶參數(shù)辉懒。
  • method:請(qǐng)求的類型抹竹,常見的get或post方法
  • url:向服務(wù)器請(qǐng)求的地址
  • async:true(異步)或 false(同步),默認(rèn)為true異步
    get方式:
xhr.open('GET','/articles/?page='+ page);
xhr.send();

post方式:

xhr.open('POST', "/articles/" + article_id + "/likes/");
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=utf-8"); //必須寫在open和send中間
 xhr.send("key=value&key2=value2");

注意:
1)post請(qǐng)求一定要設(shè)置請(qǐng)求頭的格式內(nèi)容;
2)post請(qǐng)求參數(shù)放在send里面窗轩,即請(qǐng)求體.

  1. 服務(wù)器響應(yīng)
    ajax發(fā)起請(qǐng)求某残,django后端通過url規(guī)則進(jìn)行匹配找到對(duì)應(yīng)的視圖進(jìn)行處理,然后返回處理后的結(jié)果給后端搬素,比如上面發(fā)起的是post請(qǐng)求胯舷,對(duì)應(yīng)url在django中匹配的是article_likes視圖函數(shù)
    path(r'<int:article_id>/likes/', article_likes, name='article_likes'),

article_likes視圖函數(shù)

def article_likes(request, article_id):
    article = get_object_or_404(Article, pk=article_id)

    # 判斷是否同一個(gè)IP點(diǎn)贊盈蛮,若是重復(fù)則不能繼續(xù)點(diǎn)贊,反之點(diǎn)贊數(shù)也要相加
    if 'HTTP_X_FORWARDED_FOR' in request.META:  # request.META.has_key('HTTP_X_FORWARDED_FOR'):新版取消了has_key改用in判斷
        ip = request.META['HTTP_X_FORWARDED_FOR']
    else:
        ip = request.META['REMOTE_ADDR']

    params = {'ip': ip, 'article_id': article_id}
    # 有就取這個(gè)數(shù)據(jù)淹接,如果沒有就創(chuàng)建數(shù)據(jù),返回元組(<Column: 關(guān)于>, True)
    article_likes_tuple = ArticleLikeDetail.objects.get_or_create(**params)
    article_likes_instance, article_likes_created_bolean = article_likes_tuple
    if article_likes_created_bolean:  # 如果新創(chuàng)建了
        article.increase_likes()  # 點(diǎn)贊數(shù)+1
        add_flag = True
    else:  # 如果存在則
        add_flag = False

    likes_nums = article.like_num
    result = {'likes_nums': likes_nums, 'add_flag': add_flag}

    return JsonResponse(result)

django后端根據(jù)前端ajax的請(qǐng)求進(jìn)行相應(yīng)處理,并返回處理結(jié)果巷屿。

關(guān)于JsonResponse

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)
這個(gè)類是HttpRespon的子類栽渴,它主要和父類的區(qū)別在于:
1.它的默認(rèn)Content-Type 被設(shè)置為: application/json;

2.第一個(gè)參數(shù),data應(yīng)該是一個(gè)字典類型礁鲁,當(dāng) safe 這個(gè)參數(shù)被設(shè)置為:False ,那data可以填入任何能被轉(zhuǎn)換為JSON格式的對(duì)象浊吏,比如list, tuple, set。 默認(rèn)的safe 參數(shù)是 True. 如果你傳入的data數(shù)據(jù)類型不是字典類型救氯,那么它就會(huì)拋出 TypeError的異常找田。

3.json_dumps_params參數(shù)是一個(gè)字典,它將調(diào)用json.dumps()方法并將字典中的參數(shù)傳入給該方法。

#如果這樣返回着憨,ajax還需要進(jìn)行json解析
#views.py
return HttpResponse(json.dumps({"msg":"ok!"}))

#index.html
var data=JSON.parse(data) //先通過JSON.parse 將 JSON 字符串轉(zhuǎn)換成對(duì)象墩衙。
console.log(data.msg);
#如果這樣返回,兩邊都不需要進(jìn)行json的序列化與反序列化甲抖,ajax接受的直接是一個(gè)對(duì)象
#views.py
from django.http import JsonResponse
return JsonResponse({"msg":"ok!"})

#index.html
console.log(data.msg);

javascript與python序列化和反序列化之間的轉(zhuǎn)換:
Javascript object {name:"xiaoming"} ==> json的轉(zhuǎn)換方式
JSON.stringify(data) ==> json.dumps
JSON.parse(data) ==> json.loads()

前端根據(jù)服務(wù)器相應(yīng)進(jìn)行相應(yīng)處理漆改。
前端數(shù)據(jù)獲取:
responseText 獲得字符串形式的響應(yīng)數(shù)據(jù)准谚。
responseXML 獲得XML 形式的響應(yīng)數(shù)據(jù)挫剑。
目前xml格式已經(jīng)用的不多,json用的比較多柱衔,可以通過將responseText轉(zhuǎn)換為對(duì)象進(jìn)行操作樊破。

分兩種情況處理,同步或異步
1.同步情況脆炎,前端發(fā)起請(qǐng)求需要等服務(wù)器后端處理完返回才能繼續(xù)運(yùn)行下個(gè)流程簇爆。

xhr.open('GET','/articles/?page='+ page);
xhr.send();
let res = JSON.parse(xhr.responseText); //object,將一個(gè) JSON 字符串轉(zhuǎn)換為對(duì)象

直接在send()后面處理返回來的數(shù)據(jù)硕勿。

2.異步情況粱栖,前端發(fā)起完請(qǐng)求就不管渣淤,可以繼續(xù)下一個(gè)流程渠退,等服務(wù)器處理完會(huì)調(diào)用荠锭。 異步處理相對(duì)比較麻煩,要在請(qǐng)求狀態(tài)改變事件中處理。
注冊(cè)回調(diào)函數(shù)onreadystatechange,發(fā)送一個(gè)請(qǐng)求后著摔,客戶端無法確定什么時(shí)候會(huì)完成這個(gè)請(qǐng)求摹察,所以需要用事件機(jī)制來捕獲請(qǐng)求的狀態(tài)查坪,XMLHttpRequest對(duì)象提供了onreadyStateChange事件實(shí)現(xiàn)這一功能罩阵。這類似于回調(diào)函數(shù)的做法。

onreadyStateChange事件是在readyState屬性發(fā)生改變時(shí)觸發(fā)的帽驯,readyState的值表示了當(dāng)前請(qǐng)求的狀態(tài),在事件處理程序中可以根據(jù)這個(gè)值來進(jìn)行不同的處理书闸。
readyState有五種可取值


image.png

通常在事件中判斷readyState的值是在請(qǐng)求完畢時(shí)才做處理尼变,status存儲(chǔ)了服務(wù)器端返回的Http請(qǐng)求響應(yīng)代碼,它表示請(qǐng)求的處理結(jié)果浆劲。
status:


image.png

等待請(qǐng)求處理成功嫌术,然后再進(jìn)行局部刷新。
    //注冊(cè)回調(diào)函數(shù)
    //請(qǐng)求響應(yīng)回來之后觸發(fā)
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            //獲取返回的數(shù)據(jù)
            var data = JSON.parse(xhr.responseText); //將后端傳過來的json數(shù)據(jù)解析為對(duì)象
            // console.log(data.like_nums);
            if (data.add_flag) {
                var thumbsSpan = document.querySelector(".thumbs-up>span");
                var metaSpan = document.querySelector(".article-meta>span.like>span");
                thumbsSpan.innerHTML = data.likes_nums;
                metaSpan.innerText = data.likes_nums;
                message.showSuccess("謝謝老鐵的贊~~");
            } else {
                message.showInfo("兄die牌借,您已贊過度气,謝謝~~");
            }
        }
    };

請(qǐng)求類型GET和POST區(qū)別
  1. GET請(qǐng)求會(huì)將參數(shù)拼接在url后進(jìn)行傳遞,而POST請(qǐng)求則是作為HTTP消息的實(shí)體內(nèi)容發(fā)送給WEB服務(wù)器走哺。當(dāng)然在Ajax請(qǐng)求中,這種區(qū)別對(duì)用戶是不可見的哲虾。
jquery的ajax請(qǐng)求
 // 發(fā)送請(qǐng)求
    $.ajax({
        url: "/admin/uploadImageToServer/",
        type: "POST",
        data: formData,
        // 定義文件的傳輸
        processData: false, // 必須false才會(huì)避開JQ對(duì)formdata的默認(rèn)處理
        contentType: false, // 必須false才會(huì)自動(dòng)加上正確的Content-Type
        success: function (res) {
            if (res["code"] === 2){
                swal({
                    title: "圖片上傳成功",
                    text: '',
                    type: 'success',
                    showCancelButton: false,
                    showConfirmButton: false,
                    timer: 1500
                });
                // 先清除丙躏,再將url填充
                $("#article-thumbnail-url").val();
                $("#article-thumbnail-url").val(res["data"]["image_url"]);
            }else{
                swal({
                      title: res["msg"],
                      text: '',
                      type: "error",
                      showCancelButton: false,
                      showConfirmButton: false,
                      timer: 1500
                 });
            }
        },
        error: function (err) {
            swal({
                title: '服務(wù)器錯(cuò)誤,請(qǐng)重試束凑!',
                text: '',
                type: "error",
                showCancelButton: false,
                showConfirmButton: false,
                timer: 1500
            });
        }

    });

前后端發(fā)送和后端接受處理區(qū)別:

1.GET方式
   type: "GET",   
   data: {'username': username}
   
   print(request.GET) # <QueryDict: {'username': ['admin']}>
-----------
  data: JSON.stringify({'username': username})
  print(request.GET) #<QueryDict: {'{"username":"admin"}': ['']}>
-----
  request.body = 》 b''
  
2.POST方式
    type: 'POST',
    data: {'username': username, 'email': email, 'password': password},
    
    print(request.body) #b'username=llp182&email=12%40qq.com&password=1q2w3e4r'
    print(request.POST) # <QueryDict: {'email': ['12@qq.com'], 'username': ['llp182'], 'password': ['1q2w3e4r']}>
---
    type: 'POST',
    data: JSON.stringify({'username': username, 'email': email, 'password': password}),
    print(request.body) #b'{"username":"llp182","email":"22@qq.com","password":"1q2w3e4r"}'
    print(request.POST) #<QueryDict: {'{"username":"llp182","email":"22@qq.com","password":"1q2w3e4r"}': ['']}> 

總結(jié):

以上通過 XMLHttpRequest或者封裝后的框架進(jìn)行網(wǎng)絡(luò)請(qǐng)求,這種方式已經(jīng)有點(diǎn)老舊了晒旅,配置和調(diào)用方式非常混亂汪诉,近幾年剛剛出來的Fetch提供了一個(gè)更好的替代方法废恋,它不僅提供了一種簡(jiǎn)單,合乎邏輯的方式來跨網(wǎng)絡(luò)異步獲取資源扒寄,而且可以很容易地被其他技術(shù)使用鱼鼓。下次研究分享

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市该编,隨后出現(xiàn)的幾起案子迄本,更是在濱河造成了極大的恐慌,老刑警劉巖课竣,帶你破解...
    沈念sama閱讀 217,657評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘉赎,死亡現(xiàn)場(chǎng)離奇詭異置媳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)公条,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門拇囊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人靶橱,你說我怎么就攤上這事寥袭。” “怎么了抓韩?”我有些...
    開封第一講書人閱讀 164,057評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵纠永,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我谒拴,道長(zhǎng)尝江,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評(píng)論 1 293
  • 正文 為了忘掉前任英上,我火速辦了婚禮炭序,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘苍日。我一直安慰自己惭聂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評(píng)論 6 392
  • 文/花漫 我一把揭開白布相恃。 她就那樣靜靜地躺著辜纲,像睡著了一般。 火紅的嫁衣襯著肌膚如雪拦耐。 梳的紋絲不亂的頭發(fā)上耕腾,一...
    開封第一講書人閱讀 51,443評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音杀糯,去河邊找鬼扫俺。 笑死,一個(gè)胖子當(dāng)著我的面吹牛固翰,可吹牛的內(nèi)容都是我干的狼纬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,251評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骂际,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼疗琉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起歉铝,我...
    開封第一講書人閱讀 39,129評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤没炒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體送火,經(jīng)...
    沈念sama閱讀 45,561評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拳话,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了种吸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片弃衍。...
    茶點(diǎn)故事閱讀 39,902評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坚俗,靈堂內(nèi)的尸體忽然破棺而出镜盯,到底是詐尸還是另有隱情,我是刑警寧澤猖败,帶...
    沈念sama閱讀 35,621評(píng)論 5 345
  • 正文 年R本政府宣布速缆,位于F島的核電站,受9級(jí)特大地震影響恩闻,放射性物質(zhì)發(fā)生泄漏艺糜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評(píng)論 3 328
  • 文/蒙蒙 一幢尚、第九天 我趴在偏房一處隱蔽的房頂上張望破停。 院中可真熱鬧,春花似錦尉剩、人聲如沸真慢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽黑界。三九已至,卻和暖如春皂林,著一層夾襖步出監(jiān)牢的瞬間朗鸠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工式撼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留童社,地道東北人求厕。 一個(gè)月前我還...
    沈念sama閱讀 48,025評(píng)論 2 370
  • 正文 我出身青樓著隆,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親呀癣。 傳聞我的和親對(duì)象是個(gè)殘疾皇子美浦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容