Django与Ajax交互实战:编码格式、CSRF防护及案例详解

山海之间
山海之间
发布时间:2026-10-12| 3人浏览过
原创

本文详细解析Django与Ajax交互的三种核心编码格式:urlencoded、FormData及JSON。重点讲解Django对request.POST的自动解析机制,以及处理JSON时需手动获取request.body的注意事项。同时提供CSRF认证解决方案及联动菜单、文件上传两个完整实战案例,帮助开发者掌握前后端数据高效传输技巧。

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

在前后端通信中,数据编码格式主要包含三种类型,下文将逐一进行详细演示与说明。

urlencoded
formdata
json

Ajax提交urlencoded格式数据

Ajax向后端发送数据时,默认的编码格式为urlencoded,其表现形式类似于username=abcde&password=123456。当Django后端接收到符合该编码格式的数据时,会自动将其解析并封装至request.POST中,这一处理机制与HTML 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上传文件必须借助JavaScript内置的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向Django后端发送JSON格式数据,请务必注意以下三个关键点:

  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上传文件

前端模板及JavaScript文件代码如下,请注意我们如何在表单中正确添加enctype属性,如何利用FormData对象上传文件,以及如何解决CSRF令牌验证问题。

{% 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 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。