django与ajax交互

一个动态网站是需要前端和后端进行数据交互。

什么是Ajax

Ajax是一种用于创建快速动态网页的技术。Ajax 不是一种新的编程语言,而是一种用于创建更好更快以及交互性更强的Web应用程序的技术。

  • AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML)
  • 传统的网页(不使用 Ajax)如果需要更新内容,必需重载整个网页面。
  • AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

ajax目的:提高用户体验,较少网络数据的传输量。

Ajax工作原理

网页DOM对象可以精确地对网页中的部分内容进行操作、XML作为单纯的数据存储载体使得客户端与服务器交换的只是网页内容的数据而没有网页样式等等的附属信息、XMLHttpRequest是与浏览器本身内置的request相互独立的与服务器交互的请求对象。

Ajax使用
  1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象。
var xhr;
if (window.XMLHttpRequest) { //检查浏览器的XMLHttpRequest属性,如果为真则支持XMLHttpRequest
 // IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
 xhr=new XMLHttpRequest(); 
} else {
 // IE6, IE5 浏览器执行代码
 xhr=new ActiveXObject("Microsoft.XMLHTTP"); 
}

2.向服务器发送请求

xhr.open(method,url,async);  
send(string);  //post请求时才使用字符串参数,否则不用带参数。
  • method:请求的类型,常见的get或post方法
  • url:向服务器请求的地址
  • async:true(异步)或 false(同步),默认为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请求一定要设置请求头的格式内容;
2)post请求参数放在send里面,即请求体.

  1. 服务器响应
    ajax发起请求,django后端通过url规则进行匹配找到对应的视图进行处理,然后返回处理后的结果给后端,比如上面发起的是post请求,对应url在django中匹配的是article_likes视图函数
    path(r'<int:article_id>/likes/', article_likes, name='article_likes'),

article_likes视图函数

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

    # 判断是否同一个IP点赞,若是重复则不能继续点赞,反之点赞数也要相加
    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}
    # 有就取这个数据,如果没有就创建数据,返回元组(<Column: 关于>, 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:  # 如果新创建了
        article.increase_likes()  # 点赞数+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后端根据前端ajax的请求进行相应处理,并返回处理结果。

关于JsonResponse

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)
这个类是HttpRespon的子类,它主要和父类的区别在于:
1.它的默认Content-Type 被设置为: application/json;

2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。

3.json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。

#如果这样返回,ajax还需要进行json解析
#views.py
return HttpResponse(json.dumps({"msg":"ok!"}))

#index.html
var data=JSON.parse(data) //先通过JSON.parse 将 JSON 字符串转换成对象。
console.log(data.msg);
#如果这样返回,两边都不需要进行json的序列化与反序列化,ajax接受的直接是一个对象
#views.py
from django.http import JsonResponse
return JsonResponse({"msg":"ok!"})

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

javascript与python序列化和反序列化之间的转换:
Javascript object {name:"xiaoming"} ==> json的转换方式
JSON.stringify(data) ==> json.dumps
JSON.parse(data) ==> json.loads()

前端根据服务器相应进行相应处理。
前端数据获取:
responseText 获得字符串形式的响应数据。
responseXML 获得XML 形式的响应数据。
目前xml格式已经用的不多,json用的比较多,可以通过将responseText转换为对象进行操作。

分两种情况处理,同步或异步
1.同步情况,前端发起请求需要等服务器后端处理完返回才能继续运行下个流程。

xhr.open('GET','/articles/?page='+ page);
xhr.send();
let res = JSON.parse(xhr.responseText); //object,将一个 JSON 字符串转换为对象

直接在send()后面处理返回来的数据。

2.异步情况,前端发起完请求就不管,可以继续下一个流程,等服务器处理完会调用。 异步处理相对比较麻烦,要在请求状态改变事件中处理。
注册回调函数onreadystatechange,发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态,XMLHttpRequest对象提供了onreadyStateChange事件实现这一功能。这类似于回调函数的做法。

onreadyStateChange事件是在readyState属性发生改变时触发的,readyState的值表示了当前请求的状态,在事件处理程序中可以根据这个值来进行不同的处理。
readyState有五种可取值


image.png

通常在事件中判断readyState的值是在请求完毕时才做处理,status存储了服务器端返回的Http请求响应代码,它表示请求的处理结果。
status:


image.png

等待请求处理成功,然后再进行局部刷新。
    //注册回调函数
    //请求响应回来之后触发
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4 && xhr.status == 200) {
            //获取返回的数据
            var data = JSON.parse(xhr.responseText); //将后端传过来的json数据解析为对象
            // 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,您已赞过,谢谢~~");
            }
        }
    };

请求类型GET和POST区别
  1. GET请求会将参数拼接在url后进行传递,而POST请求则是作为HTTP消息的实体内容发送给WEB服务器。当然在Ajax请求中,这种区别对用户是不可见的。
jquery的ajax请求
 // 发送请求
    $.ajax({
        url: "/admin/uploadImageToServer/",
        type: "POST",
        data: formData,
        // 定义文件的传输
        processData: false, // 必须false才会避开JQ对formdata的默认处理
        contentType: false, // 必须false才会自动加上正确的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: '服务器错误,请重试!',
                text: '',
                type: "error",
                showCancelButton: false,
                showConfirmButton: false,
                timer: 1500
            });
        }

    });

前后端发送和后端接受处理区别:

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"}': ['']}> 

总结:

以上通过 XMLHttpRequest或者封装后的框架进行网络请求,这种方式已经有点老旧了,配置和调用方式非常混乱,近几年刚刚出来的Fetch提供了一个更好的替代方法,它不仅提供了一种简单,合乎逻辑的方式来跨网络异步获取资源,而且可以很容易地被其他技术使用。下次研究分享

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容