• Django与ajax详细


    目录

    一、什么是Ajax

    二 基于jquery的Ajax实现

    ajax----->服务器------>ajaxkedudaun  

    三 案例

    四 文件上传

    请求头ContentType

    基于Form表单上传文件

    基于Ajax上传文件

    五 Ajax提交json格式数据的几种方式

    六、在Django中返回给前端json格式数据的几种方式

    七、Django内置的serializers(把对象序列化成json字符串)


    一、什么是Ajax

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。

    • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;

    • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

    AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

    具体应用场景:
    比如我们在某个网站注册账户的时候, 我们已输入就会有提示, 我们的输入是否合法, 是否重复, 但是在输入之前是没有的, 这运用的就是ajax进行处理的

    优点:

    • AJAX使用Javascript技术向服务器发送异步请求

    • AJAX无须刷新整个页面

    二 基于jquery的Ajax实现

    <button class="send_Ajax">send_Ajax</button>
    
    <script>
    
    // 使用jquery 设置点击事件发送ajax请求
    
    $(".send_Ajax").click(function(){
    
    
    
    $.ajax({
    
    // 在里面进传入相应的参数
    
    // 可以请求ajax请求的服务端地址
    
    url:"/handle_Ajax/",
    
    // 发送请求的方式, 类型
    
    type:"POST",
    
    // 向后台发送数的数据字典
    
    data:{username:"Yuan",password:123},
    
    // 后台响应成功的数据接收
    
    success:function(data){
    
    console.log(data)
    
    },
    
    
    
    // 错误信息的接收和处理   
    
    error: function (jqXHR, textStatus, err) {
    
    console.log(arguments);
    
    },
    
    // 请求完成后的动作处理
    
    complete: function (jqXHR, textStatus) {
    
    console.log(textStatus);
    
    },
    
    // 状态码的处理
    
    statusCode: {
    
    '403': function (jqXHR, textStatus, err) {
    
    console.log(arguments);
    
    },
    
    
    
    '400': function (jqXHR, textStatus, err) {
    
    console.log(arguments);
    
    }
    
    }
    
    
    
    })
    
    
    
    })
    
    
    
    </script>

    ajax----->服务器------>ajaxkedudaun  

    三 案例

    案例一、 通过Ajax,实现前端输入两个数字,服务器做加法,返回到前端页面
    在Django的 views中写上处理ajax请求的视图响应函数

    1. def test_ajax(requests):
      
      n1=int(requests.POST.get('n1'))
      
      n2=int(requests.POST.get('n2'))
      
      return HttpResponse(n1+n2)

    在前端 前端中的js代码, 其中的步骤和上面的一样

    使用jquery做一个点击事件来发送全国的csvn
    
    $("#submit").click(function () {
    
    $.ajax({
    
    url: '/test_ajax/',
    
    type: 'post',
    
    data: {
    
    n1: $("#num1").val(),
    
    n2: $("#num2").val()
    
    },
    
    success: function (data) {
    
    console.log(data)
    
    $("#sum").val(data)
    
    },
    
    
    
    })
    
    })

    在html中的代码

    <input type="text" id="num1">+<input type="text" id="num2">=<input type="text" id="sum">
    
    <button id="submit">计算</button>

     案例二 基于Ajax进行登录验证

    用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息

    首先定义好视图响应函数:
    定义视图响应函数的时候, 要先和前台沟通好数据格式, 发送数据的格式, 路由的设置等等一系列问题

    def auth(request):
    
    # 设置一个字典
    
    back_dic={'user':None,'message':None}
    
    # 根据后台发送数据的方式获取我们需要的信息
    
    name=request.POST.get('user')
    
    password=request.POST.get('password')
    
    print(name)
    
    print(password)
    
    # 根据获取到的信息和从数据库中拿出来的信息进行比对,得到最终结果然后返回给前台
    
    user=models.user.objects.filter(name=name,password=password).first()
    
    print(user)
    
    # print(user.query) # 可以打印出来查信息的sql语句
    
    # 这里我们只做了简单的校验
    
    if user:
    
    back_dic['user']=user.name
    
    back_dic['message']='成功'
    
    else:
    
    back_dic['message']='用户名或密码错误'
    
    import json
    
    # 使用json 返回给前台一个json格式的数据
    
    return HttpResponse(json.dumps(back_dic))

    前端写在script标签中的js代码, 用来发送 ajax请求

    <script>
    
    $("#submit3").click(function () {
    
    $.ajax({
    
    url: '/auth/',
    
    type: 'post',
    
    data: {
    
    'user': $("#id_name").val(),
    
    'password': $('#id_password').val()
    
    },
    
    
    
    success: function (data) {
    
    {#console.log(data)#}
    
    var data=JSON.parse(data)
    
    if (data.user){
    
    location.href='https://www.baidu.com'
    
    }else {
    
    $(".error").html(data.message).css({'color':'red','margin-left':'20px'})
    
    }
    
    }
    
    
    
    
    
    })
    
    }
    
    )</script>

    traditional:true--->可以序列化一层列表,多层不行,要转成json格式上传

    四 文件上传

    请求头ContentType

    1 application/x-www-form-urlencoded

    这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):

    POST http://www.example.com HTTP/1.1
    
    Content-Type: application/x-www-form-urlencoded;charset=utf-8
    
    
    
    user=onion&age=22

    以第一种Content Type格式发送数据的时候, 或者如果不指定编码格式,不管是form表单还是ajax传送数据时默认的编码就是unlencode,会把data这个字典转成 key1=value1&key2=valeu2 这种方式,放到request的body体里面, 然后Django会对这种格式的数据做处理, 放到POST的字典里面, 所以在视图响应函数中直接使用request.POST.get()来获取到这种方式进行数据交互

    2 multipart/form-data

    这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:

    POST http://www.example.com HTTP/1.1
    
    Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    Content-Disposition: form-data; name="user"
    
    
    
    yuan
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA
    
    Content-Disposition: form-data; name="file"; filename="chrome.png"
    
    Content-Type: image/png
    
    
    
    PNG ... content of chrome.png ...
    
    ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

    这个例子稍微复杂点。首先生成了一个 boundary (边界,分界线)用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary-- 标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。

    这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。

    上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype 属性指定,默认为 application/x-www-form-urlencoded。其实 enctype 还支持 text/plain,不过用得非常少)。

    随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。

    3 application/json

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

    JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。当需要提交的数据层次非常深的时候,就可以把数据 JSON 序列化之后再进行提交。也可以把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。

    基于Form表单上传文件

    <form action="/file_put/" method="post" enctype="multipart/form-data">
    
    用户名:<input type="text" name="name">
    
    头像:<input type="file" name="avatar" id="avatar1">
    
    <input type="submit" value="提交">
    
    </form>

    必须指定 enctype="multipart/form-data"

    视图函数:

    def file_put(request):
    
    if request.method=='GET':
    
    return render(request,'file_put.html')
    
    else:
    
    # print(request.POST)
    
    # print(request.POST)
    
    print(request.body) # 原始的请求体数据
    
    print(request.GET) # GET请求数据
    
    print(request.POST) # POST请求数据
    
    print(request.FILES) # 上传的文件数据
    
    # print(request.body.decode('utf-8'))
    
    print(request.body.decode('utf-8'))
    
    
    
    print(request.FILES)
    
    file_obj=request.FILES.get('avatar')
    
    print(type(file_obj))
    
    with open(file_obj.name,'wb') as f:
    
    for line in file_obj:
    
    f.write(line)
    
    return HttpResponse('ok')

    基于Ajax上传文件

    processData:false,     //告诉jQuery不要去处理发送的数据
    contentType:false,     // 告诉jQuery不要去设置Content-Type请求头

    $("#ajax_button").click(function () {
    
    var formdata=new FormData()
    
    formdata.append('name',$("#id_name2").val())
    
    formdata.append('avatar',$("#avatar2")[0].files[0])
    
    $.ajax({
    
    url:'',
    
    type:'post',
    
    processData:false, //告诉jQuery不要去处理发送的数据
    
    contentType:false,// 告诉jQuery不要去设置Content-Type请求头
    
    data:formdata,
    
    success:function (data) {
    
    console.log(data)
    
    
    
    }
    
    
    
    })
    
    })

    浏览器请求头为:

    Content-Type:

    multipart/form-data; boundary=----WebKitFormBoundaryA5O53SvUXJaF11O2

    五 Ajax提交json格式数据的几种方式

    在前端提交json格式数据的时候要注意前端发送数据到服务器的时候,服务器对不同编码格式的数据不同的处理方式:
    在前端编码格式对服务器处理数据时的影响:

    • 发送的数据只要是urlencoded编码:   Http请求的body体中的数据格式为:key1=value1&key2=valeu2

    • 指定编码格式为json格式:Http请求的body体中的数据格式为:"{"key1":"value1","key2":"valeu2"}",数据到后端需要自己处理

    • 提交到服务器的数据都在 request.body 里,取出来自行处理

    指定格式的时候还可以指定编码的格式:

    contentType: 
    
    'application/json;charset=utf-8'
    
    ,

    指定发送给后台的数据格式使用contentType来指定, 指定接收后台数据的格式通过datatype来指定:
    指定接收后台传回来的数据为json格式时, 如果传回来的数据不是json格式的时候, 在前端的数据解析就会出现问题,  数据就不会正常渲染到页面中,

    $("#btn").click(function () {
    
    var dic ={'name': $("#name").val(),'pwd':$("#pwd").val()}
    
    $.ajax({
    
    url: '/file/',
    
    type: 'post',
    
    dataType:'json', // 指定接收后台传回来的数据是json格式的数据时,才会正常解析
    
    data:dic,
    
    success: function (data) {
    
    alert(data.name)
    
    }
    
    })
    
    })

    方式一:
    在ajax请求中,定义一个字典, 并指定发送数据的格式为json, 并且还需要使用JSON.stringify()来将定义的字典转换成json字符串格式进行发送.,这样在Django服务器的request.body总会接收到一个json格式的字符串,只有body体中有数据, Django不会将数据进行处理放进POST或者GET字典中, 这个时候导入json模块进行反序列化(json.load(request.bady))即可将其转换为字典类型, 然后就可以当做一般的字典使用了.

    $("#ajax_test").click(function () {
    
    var dic={'name':'eric','age':18}
    
    $.ajax({
    
    url:'',
    
    type:'post',
    
    contentType:'application/json', //一定要指定格式
    
    
    
    
    
    data:JSON.stringify(dic), //转换成json字符串格式
    
    success:function (data) {
    
    console.log(data)
    
    }
    
    
    
    })
    
    
    
    })

    方式二:

    借助于formdata对象, formdata是js中的类FormData实例化出来的,  使用的时候实例化出来对象之后, 直接将要发送给后台的数据使用append方法传进去就可以了, append中的第一个参数是key第二个参数是value, value的值可以是输入框的值,也可以是一个文件对象或者, 该对象会将添加入的数据转成json格式, 要注意的是一定要指定processData:false,  contentType:false这两个参数为false, 如果不指定ajax会默认进行处理, 使用formdate的对象的好处是将数据发送回后台的时候,和使用form表单发送的http请求时没有区别的, 同时又因为本身是ajax请求, 可以实现异步提交和局部刷新; 在后台可以按照常规方式获取数据进行处理

    $("#ajax_button").click(function () {
    
    var formdata=new FormData()
    
    formdata.append('name',$("#id_name2").val())
    
    formdata.append('avatar',$("#avatar2")[0].files[0])
    
    $.ajax({
    
    url:'',
    
    type:'post',
    
    processData:false, //告诉jQuery不要去处理发送的数据
    
    contentType:false,// 告诉jQuery不要去设置Content-Type请求头
    
    data:formdata,
    
    success:function (data) {
    
    console.log(data)
    
    
    
    }
    
    
    
    })
    
    })

    总结:
          如果前端传的格式是json格式,django不会处理body中的内容,需要自己在后台取出来之后进行处理
          只有前端传的格式是urlencoded,或者form-data格式,django才会给处理,处理方式是从body体中取出来放到POST或者GET字典中, 然后在后台根据对应的请求方式进行取值就可以了

    六、在Django中返回给前端json格式数据的几种方式

    在views中接收到请求, 并经过对数据进行逻辑处理之后,返回给前端的时候, 想要返回一个json格式的数据的方式:

    方式一:
    利用Django中的JsonResponse
    利用这种方式返回数据的时候,在前端接收到的数据就是一个object对象, 也就是我们说的字典对象, 可以在前端直接使用点语法进行取值使用, 原理就是在使用JsonResponse返回数据的时候, JsonResponse在响应头中指定了contentType为'application/json', 在ajax收到数据的时候, 就会根据这个响应头将后天返回的数据进行处理, 处理成一个object对象供自己使用

    from django.http import JsonResponse
    
    def login(request):
    
    dic={'status':100,'msg':None}
    
    if request.method == 'GET':
    
    return render(request, 'login.html')
    
    # if request.is_ajax():
    
    if request.method=='POST':
    
    name=request.POST.get('name')
    
    pwd=request.POST.get('pwd')
    
    if name=='lqz' and pwd=='123':
    
    dic['msg'] = '登陆成功'
    
    # 想让前端跳转
    
    # dic['url']='http://www.baidu.com'
    
    dic['url']='/test/'
    
    else:
    
    # 返回json格式字符串
    
    dic['status']=101
    
    dic['msg']='用户名或密码错误'
    
    return JsonResponse(dic)

    方式二:

    使用json模块直接返回一个json格式的字符串, 这种方式在前端ajax接收到响应之后,不会进行转换, 因为在后台我们只是将数据序列化了一下, 返回的实质上还是HttpResponse回去一个字符串, 只不过格式是json格式的, 要想在前端想字典一样使用, 需要在前端使用JSON.parse()进行处理, 处理过后数据就变成了一个object, 就可以按照点语法在前端正常使用了.

    import json
    
    from django.http import JsonResponse
    
    def login(request):
    
    dic={'status':100,'msg':None}
    
    if request.method == 'GET':
    
    return render(request, 'login.html')
    
    # if request.is_ajax():
    
    if request.method=='POST':
    
    name=request.POST.get('name')
    
    pwd=request.POST.get('pwd')
    
    if name=='eric' and pwd=='123':
    
    dic['msg'] = '登陆成功'
    
    # 想让前端跳转
    
    # dic['url']='http://www.baidu.com'
    
    dic['url']='/test/'
    
    else:
    
    # 返回json格式字符串
    
    dic['status']=101
    
    dic['msg']='用户名或密码错误'
    
    return HttpResponse(json.dumps(dic))

    总结:
        1 后端如果返回JsonResponse,前端的ajax内部会自动将json格式字符串转换成字典
        2 后端如果返回HttpResponse,前端的ajax内部不会给你自动转换,拿到的data是字符串类型,需要手动JSON.parse(data)来转成字典

    七、Django内置的serializers(把对象序列化成json字符串)

    from django.core import serializers
    
    
    
    
    
    from django.core import serializers
    
    def test(request):
    
    book_list = Book.objects.all()
    
    ret = serializers.serialize("json", book_list)
    
    return HttpResponse(ret)
    
    
    
    # 如果不想序列化某些字段, 可以只返回时指定fields, 例如:
    
    
    
    data = serializers.serialize('json', users, fields=('username', 'id'))
    每天逼着自己写点东西,终有一天会为自己的变化感动的。这是一个潜移默化的过程,每天坚持编编故事,自己不知不觉就会拥有故事人物的特质的。 Explicit is better than implicit.(清楚优于含糊)
  • 相关阅读:
    MySql创建库 Challenge
    未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值的解决办法.
    小总结:用反射机制创建的分配数据分配器
    工厂模式的反思
    单机安装“完整”SharePoint 2010
    作业调度框架 Quartz.NET 2.0 StepByStep(2)
    UI线程同步
    每日见闻(一)
    作业调度框架 Quartz.NET 2.0 StepByStep
    基础算法(ACwing)
  • 原文地址:https://www.cnblogs.com/kylin5201314/p/13996206.html
Copyright © 2020-2023  润新知