Django如何与Ajax交互


Posted in Python onApril 29, 2021

前后端传输数据的编码格式

前后端传输数据的编码格式主要有三种, 本文接下来将详细演示。

urlencoded
formdata
json

Ajax提交urlencoded格式数据

Ajax给后台发送数据的默认编码格式是urlencoded,比如username=abcde&password=123456的形式。Django后端拿到符合urlencoded编码格式的数据都会自动帮你解析分装到request.POST中,与form表单提交的数据相同。

下面两种方式是等同的。

//手动构造数据data
$("#btnSubmit").click(function () {
    $.ajax({
        url: '/auth/', //也可以反向解析{% url 'login' %}
        type: 'post',
        data: {
            'username': $("#id_username").val(),
            'password': $('#id_password').val()
        },
        success: function (data){
            
        }
    });
};
                    
// .serialize() 方法可将<input>, <textarea> 以及 <select>表单序列化
// 成urlencoded格式数据
                      
$("#btnSubmit").click(function () {
    let data = $("#loginForm").serialize();
    $.ajax({
        url: "/auth/", //别忘了加斜杠
        type: $("#loginForm").attr('method'),
        data: data,
        success: function (data) {
         
        }
    });
});

Ajax通过FormData上传文件

Ajax上传文件需要借助于js内置对象FormData,另外上传文件时表单千万别忘了加enctype="multipart/form-data"属性。

//案例1,点击submi上传文件
$("#submitFile").click(function () {
    let formData = new FormData($("#upload-form"));
    $.ajax({
       url:"/upload/",//也可以写{% url 'upload' %}
       type:"post",
       data:formData,
       //这两个要必须写
       processData:false,  //不预处理数据  因为FormData 已经做了
       contentType:false,  //不指定编码了 因为FormData 已经做了
       success:function(data){
             console.log(data);
       }
    });
});
                       
//案例2,同时上传文件并提交其它数据
$("#submitFile").click(function () {
    //js取到文件
    let myfile = $("#id_file")[0].files[0];
    //生成一个FormData对象
    let formdata = new FormData();
    //加值
    formdata.append('name', $("#id_name").val());
    //加文件
    formdata.append('myfile', myfile);
    $.ajax({
        url: '/upload/', //url别忘了加/杠
        type: 'post',
        //这两个要必须写
        processData:false,  //不预处理数据  因为FormData 已经做了
        contentType:false,  //不指定编码了 因为FormData 已经做了
        data: formdata,
        success: function (data) {
            console.log(data);
        }
    });
});

Ajax提交Json格式数据

前后端传输数据的时候一定要确保声明的编码格式跟数据真正的格式是一致的。如果你通过Ajax发送Json格式数据给Django后端,请一定注意以下三点:

  1. contentType参数指定成application/json;
  2. 数据是真正的json格式数据;
  3. Django后端不会帮你处理json格式数据需要你自己去request.body获取并处理。
$("#submitBtn").click(function () {
    var data_obj={'name':'abcdef','password':123456};//Javascript对象
    $.ajax({
        url:'',
        type:'post',
        contentType:'application/json',  //一定要指定格式 contentType
        data:JSON.stringify(data_obj),    //转换成json字符串格式
        success:function (data) {
            console.log(data)
        }
    });
});

Ajax发送POST请求时如何通过CSRF认证

// 第一种方式直接在发送数据中加入csrfmiddlewaretoken
$("#btn").on("click",function () {
    $.ajax({
        url:"/some_url/",
        type:"POST",
        data:{
            csrfmiddlewaretoken: {{ csrf_token }}, //写在模板中,才会被渲染
        },
        success:function (data) {
    }
});
});
 
//通过jquery选择器获取csrfmiddlewaretoken
$("#btn").on("click",function () {
    $.ajax({
        url:"/some_url/",
        type:"POST",
        data:{
            csrfmiddlewaretoken:$('[name="csrfmiddlewaretoken"]').val(),
        },
        success:function (data) {
            
        }
    });
});
 
//使用jquery.cookie.js调用请求头cookie中的csrftoken
<script src="/static/jquery.cookie.js"> 
<script>
     $("#btn").on("click",function () {
     $.ajax({
        url:"/some_url/",
        type:"POST",
        headers:{"X-CSRFToken":$.cookie('csrftoken')},
        data:$("#form1").serialize()
    });
   })
</script>

Django Ajax案例1:联动下例菜单

联动下拉菜单是Web开发中一个被经常使用的应用。比如当你从一个列表从选择一个国家的时候,联动下拉菜单会同步显示属于该国家所有城市列表供用户选择。今天我们就教你如何使用Django+Ajax生成联动下拉菜单。

我们的模型如下所示:

class Country(models.Model):
    name = models.CharField(verbose_name="国家", max_length=50)

    def __str__(self):
        return self.name


class City(models.Model):
    name = models.CharField(verbose_name="城市", max_length=50)
    country = models.ForeignKey(Country, on_delete=models.CASCADE, verbose_name="国家",)

    def __str__(self):
        return self.name

我们的模板如下所示,表单中对应国家和城市下拉菜单的DOM元素id分别为id_country和id_city。当用户选择国家后,ajax会携带国家的id值向后台发送请求获得当前国家的所有城市清单,并在前端渲染显示。

{% block content %}
<h2>创建用户 - 联动下拉菜单</h2>
<form method="post" class="form-horizontal" role='form' action="">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock %}

<script src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script>
    $("#id_country").change(function() {
      var country_id = $(this).val();

      $.ajax({
        url: '/ajax/load_cities/',
        data: {
          'country_id': country_id
        },
        type: 'GET',
        dataType: 'json',
        success: function (data) {
            var content='';
            $.each(data, function(i, item){
                  content+='<option value='+item.id+'>'+item.name+'</option>'
                });
            $('#id_city').html(content)
        },

      });
    });
  </script>

Django负责处理视图Ajax请求的视图函数如下所示:

def ajax_load_cities(request):
    if request.method == 'GET':
        country_id = request.GET.get('country_id', None)
        if country_id:
            data = list(City.objects.filter(country_id=country_id).values("id", "name"))
            return JsonResponse(data, safe=False)

Django Ajax案例2:Ajax上传文件

前端模板及js文件如下所示, 请注意我们是如何在表单中加入了enctype属性,如何使用FormData上传文件,并解决了csrftoken问题的。

{% block content %}
<form action="" method="post" enctype="multipart/form-data" id="form">
    <ul class="errorlist"></ul>
    {% csrf_token %}
{{ form.as_p }}
 <input type="button" class="btn btn-info form-control" value="submit" id="btn" />
</form>
<table class="table table-striped" id="result">
</table>
{% endblock %}

{% block js %}
<script src=" https://cdn.jsdelivr.net/jquery.cookie/1.4.1/jquery.cookie.min.js ">
</script>
<script>
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function(){
   $('#btn').click(function(e){
        e.preventDefault();
        // 构建FormData对象
        var form_data = new FormData();
        form_data.append('file', $('#id_file')[0].files[0]);
        $.ajax({
        url: '/file/ajax_upload/',
        data: form_data,
        type: 'POST',
        dataType: 'json',
        // 告诉jQuery不要去处理发送的数据, 发送对象。
        processData : false,
        // 告诉jQuery不要去设置Content-Type请求头
        contentType : false,
        // 获取POST所需的csrftoken
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }},
        success: function (data) {
            if(data['error_msg']) {
                var content = '<li>'+ data['error_msg'] + '</li>';
                $('ul.errorlist').html(content);
            }
            else
            {
            var content= '<thead><tr>' +
            '<th>Name and URL</th>' +
            '<th>Size</th>' +
            '</tr></thead><tbody>';
             $.each(data, function(i, item) {
                  content = content +
                  '<tr><td>' +
                  "<a href= ' " +
                  item['url'] +
                  " '> " +
                  item['url'] +
                  '</a></td><td>' +
                  item['size'] +
                  '</td><td><tr>'
                });
             content = content + "</tbody>";
             $('#result').html(content);
             }
           },
        });
   });
 });
  </script>
{% endblock %}

Django负责处理视图Ajax请求的视图函数如下所示:

# handling AJAX requests
def ajax_upload(request):
    if request.method == "POST":
        form = FileUploadModelForm(data=request.POST, files=request.FILES)
        if form.is_valid():
            form.save()
            # Obtain the latest file list
            files = File.objects.all().order_by('-id')
            data = []
            for file in files:
                data.append({
                    "url": file.file.url,
                    "size": filesizeformat(file.file.size),
                    })
            return JsonResponse(data, safe=False)
        else:
            data = {'error_msg': "Only jpg, pdf and xlsx files are allowed."}
            return JsonResponse(data)
    return JsonResponse({'error_msg': 'only POST method accpeted.'})

以上就是Django如何与Ajax交互的详细内容,更多关于Django与Ajax交互的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python获取文件后缀名及批量更新目录下文件后缀名的方法
Nov 11 Python
解决python2.7用pip安装包时出现错误的问题
Jan 23 Python
Python中str.format()详解
Mar 12 Python
python下读取公私钥做加解密实例详解
Mar 29 Python
Pycharm学习教程(6) Pycharm作为Vim编辑器使用
May 03 Python
linux环境下的python安装过程图解(含setuptools)
Nov 22 Python
Python简单生成随机姓名的方法示例
Dec 27 Python
简单了解python关系(比较)运算符
Jul 08 Python
从pandas一个单元格的字符串中提取字符串方式
Dec 17 Python
详解Python3中的 input() 函数
Mar 18 Python
python神经网络编程实现手写数字识别
May 27 Python
python cv2.resize函数high和width注意事项说明
Jul 05 Python
Python爬虫进阶之Beautiful Soup库详解
Apr 29 #Python
win10+anaconda安装yolov5的方法及问题解决方案
Python图像处理之图像拼接
4种非常实用的python内置数据结构
Apr 28 #Python
Python基础详解之描述符
Apr 28 #Python
详解Python 3.10 中的新功能和变化
Apr 28 #Python
Python基础之数据结构详解
Apr 28 #Python
You might like
php win下Socket方式发邮件类
2009/08/21 PHP
Laravel学习教程之本地化模块
2017/08/18 PHP
一个javascript图片阅览组件
2010/11/09 Javascript
精通Javascript系列之Javascript基础篇
2011/06/07 Javascript
IE下使用cloneNode注意事项分享
2012/11/22 Javascript
基于jquery的文章中所有图片width大小批量设置方法
2013/08/01 Javascript
javascript模块化是什么及其优缺点介绍
2013/09/02 Javascript
jquery选择器大全 全面详解jquery选择器
2014/03/06 Javascript
js父页面与子页面不同时显示的方法
2014/10/16 Javascript
21个JavaScript事件(Events)属性汇总
2014/12/02 Javascript
jQuery插件multiScroll实现全屏鼠标滚动切换页面特效
2015/04/12 Javascript
详解JavaScript对象类型
2016/06/16 Javascript
js利用clipboardData实现截屏粘贴功能
2016/10/12 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
webpack构建vue项目的详细教程(配置篇)
2017/07/17 Javascript
在Vue组件上动态添加和删除属性方法
2018/02/23 Javascript
jQuery的ztree仿windows文件新建和拖拽功能的实现代码
2018/12/05 jQuery
微信小程序使用map组件实现检索(定位位置)周边的POI功能示例
2019/01/23 Javascript
ES6中字符串的使用方法扩展
2019/06/04 Javascript
[00:28]DOTA2北京网鱼队选拔赛
2015/04/08 DOTA
[01:04:09]DOTA2-DPC中国联赛 正赛 iG vs VG BO3 第二场 2月2日
2021/03/11 DOTA
[54:15]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第二场2月1日
2021/03/11 DOTA
Python利用pandas计算多个CSV文件数据值的实例
2018/04/19 Python
在Windows中设置Python环境变量的实例讲解
2018/04/28 Python
Django-Model数据库操作(增删改查、连表结构)详解
2019/07/17 Python
python原类、类的创建过程与方法详解
2019/07/19 Python
浅谈pymysql查询语句中带有in时传递参数的问题
2020/06/05 Python
使用CSS实现弹性视频html5案例实践
2012/12/26 HTML / CSS
给实习单位的感谢信
2014/02/01 职场文书
《再别康桥》教学反思
2014/02/12 职场文书
高一新生军训感言
2014/03/02 职场文书
2014年小学植树节活动方案
2014/03/02 职场文书
学校综治宣传月活动总结
2014/07/02 职场文书
企业法人授权委托书范本
2014/09/23 职场文书
电影红河谷观后感
2015/06/11 职场文书
公安纪律作风整顿心得体会
2016/01/23 职场文书