django08--前端jQuery的Ajax、自带序列化组件

1 Ajax介绍

# Ajax  Asynchronous Javascript And XML
  异步提交
  局部刷新
    eg:github注册
	 动态获取用户名实时的跟后端确认并实时展示的前端(局部刷新)

# 1.翻译成中文就是“异步的Javascript和XML”
  即:使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)
 
# 2.不是新的编程语言,而是一种使用现有标准的新方法

# 3.最大的优点是
  在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
     这一特点给用户的感受是在不知不觉中完成请求和响应过程
        
# 4.不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
  同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。


Ajax我们只学习jQuery封装之后的版本(不学原生的 原生的复杂并且在实际项目中也一般不用)
所以我们在前端页面使用ajax的时候需要确保导入了jQuery
ps:并不只有jQuery能够实现ajax,其他的框架也可以 但是换汤不换药 原理是一样的

1.1 基本格式

$.ajax({
    // 1.指定朝哪个后端发送ajax请求
    url:'',  // 不写就是朝当前地址提交
    
    // 2.请求方式
    type:'post',  // 不指定默认就是get 都是小写
    
    // 3.数据
    data:{'username':'jason','password':123}   # 在Python,是字典;在前端:是自定义对象
    
    // 4.请求数据的编码格式
    contentType:'application/json',
    
    // 5.响应数据的格式  自动反序列化
    dataType:'json',  // 以后推荐加上 增加程序兼容性
    
    // 6.异步回调函数:当后端给你返回结果的时候会自动触发 args接受后端的返回结果
    success:function (args) {
        console.log(typeof args)
    }
})



# 前后端交互,数据是JSON时

# 后端返回Json格式
  采用 JsonResponse 返回  或 利用json模块序列化后,再HttpResponse返回
	
# 前端接受:
  1.后端用JsonResponse返回
    前端回调函数 会自动反序列化成 json对应的格式
    
  2.后端用HttpResponse返回
    回调函数不会自动帮你反序列化,指定参数 或 手动反序列化
      1.手动反序列化 JSON.parse() 
      2.在ajax里面配置一个参数
        dataType:'json' 

1.2 小例子

"""
页面上有三个input框
  在前两个框中输入数字 点击按钮 朝后端发送ajax请求
  后端计算出结果 再返回给前端动态展示的到第三个input框中
  (整个过程页面不准有刷新,也不能在前端计算)
"""

##### my_ajax.html
<input type="text" id="i1">+<input type="text" id="i2">=<input type="text" id="i3">
<button id="btn">提交</button>

<script>
$('#btn').click(function () {
    // 朝后端发送ajax请求
    $.ajax({
        // 1.指定朝哪个后端发送ajax请求
        url:'',  // 不写就是朝当前地址提交
        // 2.请求方式
        type:'post',  // 不指定默认就是get 都是小写
        // 3.数据
        # data:{'username':'jason','password':123}   # 在Python,是字典;在前端:是自定义对象
        data:{'i1':$('#i1').val(),'i2':$('#i2').val()},
        // 4.回调函数:当后端给你返回结果的时候会自动触发 args接受后端的返回结果
        success:function (args) {
            {#alert(args)  // 通过DOM操作动态渲染到第三个input里面#}
            {#$('#d3').val(args)#}
            console.log(typeof args)
        }
    })
})
 </script>             
            
        
##### views.py
            
from django.shortcuts import render,HttpResponse

import json
from django.http import JsonResponse

def ab_ajax(request):
    if request.method == "POST":
        # print(request.POST)  # <QueryDict: {'username': ['jason'], 'password': ['123']}>
        i1 = request.POST.get('i1')
        i2 = request.POST.get('i2')
        # 先转成整型再加
        i3 = int(i1) + int(i2)
        # print(i3)
        d = {'code':100,'msg':i3}
        return HttpResponse(json.dumps(d))
        # return JsonResponse(d)
    return render(request,'index.html')        

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

前后端传输数据的时候,一定要确保 编码格式 跟 数据真正的格式 是一致的

# 前提:
  # 1.可以发送网络请求的标签
    1.浏览器地址栏直接输入url回车 GET请求
    2.a标签href属性		GET请求
    3.form表单			GET请求/POST请求
    4.ajax			GET请求/POST请求	
    
  # 2.get请求的数据: 直接放在url后面的   编码格式 由 url编码决定
    eg: url?username=jason&password=123
        
  # 3.post请求的数据: 存放请求体中  编码格式 由 content-Type决定 (学习这个)

  # 4.可以朝后端发送post请求的方式
      form表单 和 ajax请求


# 前后端传输数据的编码格式: content-Type
  content-Type在请求头中,用于标识数据的编码格式
  后端通过该参数的不同 采取对应的处理措施 来操作数据


# 具体格式:
  urlencoded
  formdata
  json


# 前端查看content-Type: 
  浏览器--F12--network--name(最新的页面请求)--Headers--Request Headers--content-type:具体格式

3 form表单发送数据

# form表单+post请求 发送不同格式的数据

# 1.urlencoded   默认的数据编码格式
  # 指定编码格式
  enctype="application/x-www-form-urlencoded"  

  # 数据格式
  键值对  eg:username=jason&password=123
    
  # 后端获取:request.POST中
  django后端针对符合urlencoded编码格式的数据  自动解析封装到request.POST中
  

# 2.form-data
  # 指定编码格式
  enctype="multipart/form-data"

  # 数据格式
  键值对 和 文件
    
  # 后端获取:
  键值对 :request.POST中
  文件   :request.FILES中
 

# 3.json
  form表单无法发送json格式数据

4 Ajax发送数据

4.1 ajax发送urlencoded格式数据

# urlencoded   默认的数据编码格式
  # 指定编码格式
  参数 contentType  不用指定

  # 数据格式
  键值对  eg:username=jason&password=123
    
  # 后端获取:request.POST

4.2 ajax发送json格式数据

# 前提
  python中序列化反序列化
    import json
    json.dumps()   python --> json
    json.loads()   json --> python
      # json.loads括号内 参数 默认为json格式
        但如果传入了一个二进制格式的数据 内部会自动解码 再反序列化

  Js中序列化反序列化
    JSON.stringify()  js  --> json
    JSON.parse()     json --> js


# json格式
  # 指定编码格式
  contentType='application/json'

  # 后端获取:request.body中  二进制形式
    django针对接受的json格式的数据 不会做任何的处理,以二进制的形式在request.body中
	
	
# request对象方法补充
  request.is_ajax()  # 判断当前请求是否是ajax请求 返回布尔值
    
    

# 总结:
  1.contentType参数指定成:application/json
  2.数据是真正的json格式数据
  3.django后端不会处理json格式数据 需要手动去request.body获取并处理



# eg:
<script>
    $('#d1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            data:JSON.stringify({'username':'jason','age':25}),  // 前端编译成json格式
            contentType:'application/json',  // Ajax向后端发送数据的编码格式
            success:function () {
            }
        })
    })
</script>



def ab_json(request):
    if request.is_ajax():
        if request.method == 'POST':
            json_bytes = request.body
            json_str = json_bytes.decode('utf-8')
            json_dict = json.loads(json_str)

            # json.loads括号内 如果传入了一个二进制格式的数据 那么内部自动解码再反序列化
            json_dict = json.loads(json_bytes)
            print(json_dict)
    return render(request,'ab_json.html')

4.3 ajax发送文件(fromdata)

# ajax发送文件
  需要借助于js内置对象FormData
    
        
# 总结:
  1.需要利用内置对象FormData
    // 1 需要先实例化一个FormData内置对象
    let formDateObj = new FormData();
    // 2 添加普通的键值对
    formDateObj.append('username',$('#d1').val());
    formDateObj.append('password',$('#d2').val());
    // 3 添加文件对象
    formDateObj.append('myfile',$('#d3')[0].files[0])
        	
  2.需要指定两个关键性的参数
  contentType:false,  // 不需使用任何编码 django后端能够自动识别formdata对象
  processData:false,  // 告诉你的浏览器 不要对你的数据进行任何处理
        
  3.后端获取:
  键值对 :request.POST中
  文件   :request.FILES中

    
<script>
    // 点击按钮朝后端发送普通键值对和文件数据
    $('#d4').on('click',function () {
        // 1 需要先实例化一个FormData内置对象
        let formDateObj = new FormData();
        
        // 2 添加普通的键值对
        formDateObj.append('username',$('#d1').val());
        formDateObj.append('password',$('#d2').val());
        
        // 3 添加文件对象
        formDateObj.append('myfile',$('#d3')[0].files[0])    
        // $('#d3')--js标签对象集合   [0]--具体的js标签对象	.files[0]--再其具体的文件对象
        
		// 4 将对象基于ajax发送给后端
        $.ajax({
            url:'',
            type:'post',
            data:formDateObj,  // 直接将对象放在data后面即可

            // ajax发送文件必须要指定的两个参数
            contentType:false,  // 不需使用任何编码 django后端能够自动识别formdata对象
            processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理
             //原因:默认情况下jQuery会将数据预处理成username=jason&age=20格式

            success:function (args) {
            }
        })


    })
</script>

def ab_file(request):
    if request.is_ajax():
        if request.method == 'POST':
            print(request.POST)
            print(request.FILES)
    return render(request,'ab_file.html')

5 自带的序列化组件(了解)

# Django内置的serializers

  但实际开发中,Django 用的序列化组件是 drf


# 需求:在前端给我获取到后端用户表里面所有的数据(json格式) 并且要是列表套字典:[{},{},{},{},{}]
import json
from django.http import JsonResponse
from django.core import serializers    # 自带的序列化模块

def ab_ser(request):
	user_queryset = models.User.objects.all()
    
    # 方式一:用Django模板语法,前端自己写for循环获取
    return render(request,'ab_ser.html',locals())  
    """
    [ { % for user_obj in user_queryset %}
    	{ {{user_obj}} }
    { % endfor %} ]
    """
    
    
	# 但若是前后端是分离的,方式一就不可行了,前端不能使用Django的模板语法!
    
    # 方式二:自己构建数据样式,再利用JsonResponse 返回json对象
    # 构建特定样式的json数据:[{},{},{},{},{}]
	user_list = []
    for user_obj in user_queryset:
		tmp = {
            'pk':user_obj.pk,
            'username':user_obj.username,
            'age':user_obj.age,
            'gender':user_obj.get_gender_display()
         }
         user_list.append(tmp)
    return JsonResponse(user_list,safe=False)  
    # 注意:safe参数,因为JsonResponse 正常只能序列化字典,其他可迭代对象,要设置该参数为False
    
    
"""
方式二的结果:
[
 {"pk": 1, "username": "jason", "age": 25, "gender": "male"}, 
 {"pk": 2, "username": "egon", "age": 31, "gender": "female"},
 {"pk": 3, "username": "kevin", "age": 32, "gender": "others"}, 
 {"pk": 4, "username": "tank", "age": 40, "gender": 4}
]
""" 
    
     
    # 但若是数据字段比较多时,自己来构建数据样式就不合理!

    # 方式三:Django后端提供序列化模块 serializers
	#   会自动帮你将数据变成json格式的字符串 并且内部非常的全面
    res = serializers.serialize('json',user_queryset)
    return HttpResponse(res)


"""
方式三的结果:
[
{   "model": "app01.user", 
    "pk": 1, 
    "fields": {"username": "jason", "age": 25, "gender": 1}}, 
    
{   "model": "app01.user", 
    "pk": 2, 
    "fields": {"username": "egon", "age": 31, "gender": 2}}, 
    
{   "model": "app01.user", 
    "pk": 3, 
    "fields": {"username": "kevin", "age": 32, "gender": 3}},
     
{   "model": "app01.user", 
    "pk": 4, 
    "fields": {"username": "tank", "age": 40, "gender": 4}}
]
"""



# 总结:
  前后端分离的项目
    作为后端开发的你只需要写代码将数据处理好  能够json序列化返回给前端即可 
    再写一个接口文档 告诉前端每个字段代表的意思即可
        
  写接口就是利用序列化组件渲染数据,然后写一个接口文档 该交代的交代一下就完事

6 ajax结合sweetalert

"""
自己要学会如何拷贝
学会基于别人的基础之上做修改    --sweetalert 弹出框插件
研究各个参数表示的意思 然后找葫芦画瓢
"""

# eg:ajax结合sweetalert  二次确认删除
<script>
	$('.del').on('click',function () {
		// 先将当前标签对象存储起来
        let currentBtn = $(this);
        
        // 二次确认弹框
        swal({
          title: "你确定要删吗?",
          text: "你可要考虑清除哦,可能需要拎包跑路哦!",
          type: "warning",
          showCancelButton: true,
          confirmButtonClass: "btn-danger",
          confirmButtonText: "是的,老子就要删!",
          cancelButtonText: "算了,算了!",
          closeOnConfirm: false,
          closeOnCancel: false,
          showLoaderOnConfirm: true
        },
            
        function(isConfirm) {
          if (isConfirm) {
                // 朝后端发送ajax请求删除数据之后 再弹下面的提示框
                $.ajax({
                    {#url:'/delete/user/' + currentBtn.attr('delete_id'),  // 1 传递主键值方式1 直接放在URL上#}
                    url:'/delete/user/',  // 2 放在请求体里面
                    type:'post',
                    data:{'delete_id':currentBtn.attr('delete_id')},
                    success:function (args) {  		// args = {'code':'','msg':''}
                        // 判断响应状态码 然后做不同的处理
                        if(args.code === 1000){
                            swal("删了!", args.msg, "success");
                            // 更新当前的用户展示页面
                            // 1.lowb版本 直接刷新当前页面
                            {#window.location.reload()#}
                            // 2.利用DOM操作 动态刷新 -- 直接将当前的数据行进行删除
                            currentBtn.parent().parent().remove()
                        }
                        else{
                            swal('完了','出现了未知的错误','info')
                        }
                    }

                })

          } 
        else {
            swal("怂逼", "不要说我认识你", "error");
          }
        });
    })

</script>
posted @ 2021-09-10 01:34  Edmond辉仔  阅读(41)  评论(0)    收藏  举报