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 相关文章推荐
Django Admin实现上传图片校验功能
Mar 06 Python
利用Python如何生成随机密码
Apr 20 Python
python 生成器生成杨辉三角的方法(必看)
Apr 10 Python
在java中如何定义一个抽象属性示例详解
Aug 18 Python
python with提前退出遇到的坑与解决方案
Jan 05 Python
Python图像处理之简单画板实现方法示例
Aug 30 Python
详解如何为eclipse安装合适版本的python插件pydev
Nov 04 Python
Python的UTC时间转换讲解
Feb 26 Python
django多文件上传,form提交,多对多外键保存的实例
Aug 06 Python
pytorch自定义初始化权重的方法
Aug 17 Python
浅析Python 多行匹配模式
Jul 24 Python
Python四款GUI图形界面库介绍
Jun 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
星际争霸中的对战模式介绍
2020/03/04 星际争霸
PHP针对redis常用操作实例详解
2019/08/17 PHP
收藏Javascript中常用的55个经典技巧
2007/08/12 Javascript
javascript 面向对象编程 聊聊对象的事
2009/09/17 Javascript
javascript中字符串拼接需注意的问题
2010/07/13 Javascript
Eclipse去除js(JavaScript)验证错误
2014/02/11 Javascript
jQuery简单实现图片预加载
2015/04/20 Javascript
第十篇BootStrap轮播插件使用详解
2016/06/21 Javascript
Bootstrap Navbar Component实现响应式导航
2016/10/08 Javascript
Vue.js Ajax动态参数与列表显示实现方法
2016/10/20 Javascript
微信小程序 require机制详解及实例代码
2016/12/14 Javascript
HTML5+JS+JQuery+ECharts实现异步加载问题
2017/12/16 jQuery
vue封装一个简单的div框选时间的组件的方法
2019/01/06 Javascript
vue项目中使用vue-layer弹框插件的方法
2020/03/11 Javascript
Element Dropdown下拉菜单的使用方法
2020/07/26 Javascript
如何利用JS将手机号中间四位变成*号
2020/09/29 Javascript
Python使用scrapy采集数据过程中放回下载过大页面的方法
2015/04/08 Python
python实现redis三种cas事务操作
2017/12/19 Python
python实现图书管理系统
2018/03/12 Python
Python和Go语言的区别总结
2019/02/20 Python
pycharm第三方库安装失败的问题及解决经验分享
2020/05/09 Python
win7上tensorflow2.2.0安装成功 引用DLL load failed时找不到指定模块 tensorflow has no attribute xxx 解决方法
2020/05/20 Python
OpenCV 之按位运算举例解析
2020/06/19 Python
如何使用python写截屏小工具
2020/09/29 Python
一款css实现的鼠标经过按钮的特效
2014/09/11 HTML / CSS
在html5的Canvas上绘制椭圆的几种方法总结
2013/01/07 HTML / CSS
Bealls Florida百货商店:生活服饰、家居装饰和鞋子
2018/02/23 全球购物
eharmony澳大利亚:网上约会服务
2020/02/29 全球购物
汽车销售顾问求职自荐信
2014/01/01 职场文书
扩大国家免疫规划实施方案
2014/03/21 职场文书
高中美术教师事迹材料
2014/08/22 职场文书
2014年大学生村官工作总结
2014/11/19 职场文书
医院科室评语
2015/01/04 职场文书
2015年社区重阳节活动总结
2015/07/30 职场文书
纯CSS实现酷炫的霓虹灯效果
2021/04/13 HTML / CSS
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/07 PostgreSQL