【15.0】Ajax进阶操作

【一】前后端传输数据的编码格式(contentType)

主要研究POST请求数据的编码格式

因为GET请求数据就是直接放在url后面的

  • 可以朝后端发送post请求的方式
    • form请求
    • ajax请求

【1】form表单

  • 前后端传输数据的格式

    • urlencoded

    • formdata

    • json

<form action="" method="post" enctype="text/plain"></form>
<form action="" method="post" enctype="application/x-www-form-urlencoded"></form>
<form action="" method="post" enctype="multipart/form-data"></form>

【2】编码格式

  • form表单默认的编码格式是urlencoded
    • 通过查看请求头中的 Content-Type 参数
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:27
Content-Type:application/x-www-form-urlencoded
  • 携带数据格式
username=666666&password=66
  • Django后端针对 urlencoded 编码格式的数据会自动帮我们解析封装到 request.POST

  • 如果编码格式改为 formdata ,那么针对普通的键值对还是解析到 request.POST 中,而其他文件格式的数据解析到 request.FILES

  • form表单无法发送json格式数据

【3】Ajax

Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8
Cache-Control:no-cache
Connection:keep-alive
Content-Length:31
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
  • 默认的编码格式是 urlencoded
  • 数据格式
username=dream&password=1314521
  • Django后端针对 urlencoded 编码格式的数据会自动帮我们解析封装到 request.POST
  • --->username=dream&password=1314521

【4】代码演示

(1)后端

def index(request):
    if request.method == 'POST':
        print(request.POST)
        # <QueryDict: {'username': ['dream'], 'password': ['1314521']}>
        print(request.FILES)
        # <MultiValueDict: {'img_file': [<InMemoryUploadedFile: 作用域链.drawio.png (image/png)>]}>
    return render(request, 'index.html')

(2)前端

<form action="" method="post" enctype="multipart/form-data">
    <p>username: <input type="text" name="username" class="form-control"></p>
    <p>password: <input type="password" name="password" class="form-control"></p>
    <p>file: <input type="file"></p>
    <p><input type="submit" class="btn btn-success"></p>
    <p><input type="button" class="btn btn-danger" value="按钮" id="d1"></p>
</form>

<script>
    $("#d1").click(function () {
        $.ajax({
            url: '',
            type: 'POST',
            data: {"username": "dream", "password": 1314521},
            success: function (args) {

            },
        })
    })
</script>

【二】Ajax发送JSON格式数据

  • 前后端传输数据的时候一定要保证编码格式数据与真正的数据格式是一致的

【1】引入

(1)后端

def ab_json(request):
    if request.method == 'POST':
        print(request.POST) #<QueryDict: {}>
    return render(request, 'ab_json.html')

(2)前端

<button class="btn btn-danger" id="d1">点我</button>

<script>
    $('#d1').click(function () {
        $.ajax({
            url: '',
            type: 'post',
            // 前端数据转JSON格式数据 :JSON.stringify
            data: JSON.stringify({"username": "dream", "password": 521521}),
            // 不指定参数,默认就是 urlencoded
            contentType: 'application/json',
            success: function (args) {

            }
        })
    })
</script>
  • 请求标头携带的数据格式
    • 已成功转换为JSON格式
{"username":"dream","password":521521}

【2】后端

  • 接收到的数据为空
def ab_json(request):
    if request.method == 'POST':
        print(request.POST) #<QueryDict: {}>
    return render(request, 'ab_json.html')
  • Django针对JSON格式的数据不会做任何处理

  • 针对JSON格式的数据需要自己手动处理

  • 解决办法

def ab_json(request):
    print(request.is_ajax())  # True
    if request.method == 'POST':
        print(request.POST)  # <QueryDict: {}>

    print(request.body)  # 返回的是二进制数据 :b'{"username":"dream","password":521521}'
    # 针对JSON格式的数据需要自己手动处理
    json_bytes = request.body

    # (1)方式一:先解码 再转换数据格式
    json_str = json_bytes.decode('utf-8')
    json_dict = json.loads(json_str)
    print(json_dict, type(json_dict))  # {'username': 'dream', 'password': 521521} <class 'dict'>

    # (2)方式二:json.loads(二进制数据) 内部可以自动解码再反序列化
    json_dict_loads = json.loads(json_bytes)
    print(json_dict_loads, type(json_dict_loads))  # {'username': 'dream', 'password': 521521} <class 'dict'>


    return render(request, 'ab_json.html')

【3】总结

(1)注意参数

  • 前端在通过Ajax请求发送数据的时候,一定要注参数修改
// 不指定参数,默认就是 urlencoded
contentType: 'application/json',

(2)符合JSON数据格式

  • 数据是真正的JSON格式数据
发送的数据一定要符合JSON格式
或经过JSON序列化再传输

(3)手动处理前端传入的JSON数据

  • Django后端不会帮我们处理JSON格式数据,需要自己手动处理request.body中的数据
通过Ajax传过来的数据是二进制数据
在request.body中
要经过自己的反序列化才能拿到我们想要的数据

【三】Ajax发送文件数据

【1】发送方法(formdata对象)

  • Ajax发送文件数据需要借助js内置对象formdata

(1)前端

<p>username: <input type="text" name="username" id="d1"></p>
<p>password: <input type="password" name="password" id="d2"></p>
<p>file: <input type="file" id="d3"></p>

<button id="btn" class="btn btn-danger">提交</button>


<script>
    // 点击按钮向后端发送普通键值对数据和文件数据
    $("#btn").on('click', function () {
        // (1)先生成一个内置对象
        let formDataObj = new FormData();

        // (2)支持添加普通的键值对
        formDataObj.append('username', $("#d1").val());
        formDataObj.append('password', $("#d2").val());

        // (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
        formDataObj.append('myfile', $("#d3")[0].files[0]);

        // (4)基于Ajax,将文件对象发送给后端
        $.ajax({
            url: '',
            type: 'post',
            // 直接将对象放到data里面即可
            data: formDataObj,

            // Ajax发送文件必须添加的两个参数
            // 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
            contentType: false,
            // 告诉浏览器不要对我的数据进行任何处理
            processData: false,

            success: function (args) {

            }
        })
    })
</script>

(2)后端

def ab_file(request):
    if request.is_ajax():
        if request.method == 'POST':
            print('POST::>>', request.POST)
            # 普通键值对放在了  request.POST   中
            # POST::>> <QueryDict: {'username': ['dream'], 'password': ['666']}>
            print('FILES::>>', request.FILES)
            # 文件数据放在了  request.FILES   中
            # FILES::>> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: img.png (image/png)>]}>

    return render(request, 'ab_file.html')

【2】发送文件数据的格式

// 点击按钮向后端发送普通键值对数据和文件数据
$("#btn").on('click', function () {
    // (1)先生成一个内置对象
    let formDataObj = new FormData();

    // (2)支持添加普通的键值对
    formDataObj.append('username', $("#d1").val());
    formDataObj.append('password', $("#d2").val());

    // (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
    formDataObj.append('myfile', $("#d3")[0].files[0]);

    // (4)基于Ajax,将文件对象发送给后端
    $.ajax({
    url: '',
    type: 'post',
    // 直接将对象放到data里面即可
    data: formDataObj,

    // Ajax发送文件必须添加的两个参数
    // 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
    contentType: false,
    // 告诉浏览器不要对我的数据进行任何处理
    processData: false,

    success: function (args) {

    }
})

【3】小结

(1)借助FormData对象

  • Ajax发送文件数据需要利用内置对象FormData
// (1)先生成一个内置对象
let formDataObj = new FormData();

// (2)支持添加普通的键值对
formDataObj.append('username', $("#d1").val());
formDataObj.append('password', $("#d2").val());

// (3)支持添加文件对象 ---> 先拿到标签对象 ----> 再拿到文件对象
formDataObj.append('myfile', $("#d3")[0].files[0]);

(2)必须携带两个参数

  • 需要指定两个关键性的参数
// Ajax发送文件必须添加的两个参数
// 不需要使用任何编码 -  Django后端能自动识别 formdata 对象
contentType: false,
// 告诉浏览器不要对我的数据进行任何处理
processData: false,

(3)后端解析数据

  • Django后端能直接自动识别到FormData对象
    • 将内部的普通键值对自动解析并封装到request.POST
    • 将内部的文件数据自动解析并封装到request.FILES
print('POST::>>', request.POST)
# 普通键值对放在了  request.POST   中
# POST::>> <QueryDict: {'username': ['dream'], 'password': ['666']}>

print('FILES::>>', request.FILES)
# 文件数据放在了  request.FILES   中
# FILES::>> <MultiValueDict: {'myfile': [<InMemoryUploadedFile: img.png (image/png)>]}>

【补充】request方法判断ajax

request.is_ajax()
  • 返回当前请求是否是ajax请求,返回布尔值
print(request.is_ajax())

# 正常浏览器网址回车提交的是 GET 请求 - 结果是False
# 当我们发送ajax请求后 - 结果是True
posted @ 2024-03-18 23:00  Chimengmeng  阅读(13)  评论(0编辑  收藏  举报