• ajax


    stringify与parse方法

    JavaScript中关于JSON对象和字符串转换的两个方法:

    JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象 

    JSON.parse('{"name":"alex"}');
    JSON.parse('{name:"alex"}') ;      // 错误
    JSON.parse('[18,undefined]') ;     // 错误

    JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 

    JSON.stringify({"name":"alex"})
    python中数据类型的转化
    1. python对象 ——》 json字符串
    	import json
    	json.dumps(python的数据类型)
    2. json字符串 ——》python对象
    	json.loads(json字符串)		
    3.支持的数据类型  字符串 数字 布尔值 列表 字典 None
    
    django在视图函数中发送json格式的数据
    	1,使用json模块   json.dumps() ,ajax还需要进行json解析
    	#views.py
    	return HttpResponse(json.dumps({"msg":"ok!"}))
    
    	#index.html
    	var data=json.parse(data)
    	console.log(data.msg);
    	2,使用 JsonResponse  可以发送字典,两边都不需要进行json的序列化与反序列化,ajax接受的直接是一个对象
    		#views.py
    		from django.http import JsonResponse
    		return JsonResponse({"msg":"ok!"})
    
    		#index.html
    		console.log(data.msg);
    		
    		JsonResponse 对象:
    		class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)
    		这个类是HttpRespon的子类,它主要和父类的区别在于:
    		a).它的默认Content-Type 被设置为: application/json
    		b).第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。
    		c).json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。
    	3,使用Django内置的serializers模块,可以发送queryset数据库对象
    		def books_json(request):
    			book_list = models.Book.objects.all()[0:10]
    			from django.core import serializers
    			ret = serializers.serialize("json", book_list)
    			return HttpResponse(ret)
    

      

    ajax

    AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)

    向服务端发请求的方法:
    1. 在浏览器的地址栏上输入URL 回车 —— 》GET
    2. 使用form表单 提交 —— 》 GET/POST
      1. action # 提交的地址
      2. method # 提交方式
      3. 上传文件的时候 enctype="multipart/form-data"
      4. input标签要有name属性
      5. 要有一个type=sumbit的按钮或者input
    3. a标签 —— 》GET
    4. Ajax

    使用ajax局部刷新页面例子,计算两个数相加之和 浏览器获取两个数,通过ajax发送到后端,后端相加后将结果返回给浏览器,浏览器的结果框局部刷新渲染这个结果

    csrf验证是防止别的程序发post请求到我的网址,对于自己写的网页我们给每个访问网址的浏览器加上一个cookie,然后让我们的程序发post请求时也带一个cookie,当浏览器发请求时经过中间件 process_request获取浏览器带的cookie,然后process_view获取了post请求中的cookie,并和浏览器带的cookie进行比较,一致允许访问,不一致拒绝访问

    在post表单中加{% csrf_token %} 可以给post中带cookie,并给浏览器中加cookie

    给views中的函数加装饰器   @ensure_csrf_cookie ,也可以给浏览器加cookie, CBV的views只能把装饰器加到 dispatch() 方法上

    # 不考虑csrf的ajax提交post请求(注掉中间件)
    
    
    # urls.py
    from django.conf.urls import url
    from django.contrib import admin
    
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^index/', views.index),
        url(r'^calc/', views.calc),
    ]
    
    
    # views.py
    from django.shortcuts import render,HttpResponse
    
    def index(request):
        return render(request,'index.html')
    def calc(request):
        l1 = int(request.POST.get('i1'))
        l2 = int(request.POST.get('i2'))
        res = l1+l2
        return HttpResponse(res)
    
    
    # index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h2>ajex提交</h2>
    <input type="text" id="i1">+
    <input type="text" id="i2">=
    <input type="text" id="i3">
    <button type="submit" id="b1">计算</button>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script>
        $('#b1').click(function () {
            var i1=$('#i1').val();
            var i2=$('#i2').val();
            $.ajax({
                url:'/calc/',		# 请求地址是 /calc/
                type:'post',
                data:{
                    'i1':i1,
                    'i2':i2
                },
                success:function (res) {	# res是 calc函数的返回值,calc返回的是相加后的结果,这里接收
                    console.log(res);
                    $('#i3').val(res);
    
                }
            })
    
        })
    </script>
    
    </body>
    </html>
    
    # 考虑csrf的情况,需要给ajax的post请求加上cookie
    
    方法一:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
    # index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h2>ajex提交</h2>
    {% csrf_token %}
    <input type="text" id="i1">+
    <input type="text" id="i2">=
    <input type="text" id="i3">
    <button type="submit" id="b1">计算</button>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script>
        $('#b1').click(function () {
            var i1=$('#i1').val();
            var i2=$('#i2').val();
            $.ajax({
                url:'/calc/',
                type:'post',
                data:{
                    'i1':i1,
                    'i2':i2,
    				 "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
                },
                success:function (res) {
                    console.log(res);
                    $('#i3').val(res);
    
                }
            })
    
        })
    </script>
    
    </body>
    </html>
    
    方法二:通过获取返回的cookie中的字符串 放置在请求头中发送
    ...
    {% csrf_token %}
    ...
    $.ajax({
                url:'/calc/',
                type:'post',            
                headers:{"X-CSRFToken":$.cookie('csrftoken')}, //从Cookie取csrftoken,并设置到请求头中
                data:{
                    'i1':i1,
                    'i2':i2,				
                },
                success:function (res) {
                    console.log(res);
                    $('#i3').val(res);
    
                }
            })
    ...
    
    方法三:自己写一个getCookie的js文件
    因为是js文件需要放到静态文件中,所以把以下代码写在static目录下,然后命名为ajax_setup.js ,然后在index.html页面链接js    <script src="/static/ajax_setup.js"></script>
    
    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    var csrftoken = getCookie('csrftoken');
    
    
    // 每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置
    
    
    function csrfSafeMethod(method) {
      // these HTTP methods do not require CSRF protection
      return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    }
    
    $.ajaxSetup({
      beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      }
    });
    
    
    如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。
    如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。
    这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
    推荐在 views 函数里加装饰器,然后在模板中就不用写 {% csrf_token %} 了
    
    django.views.decorators.csrf import ensure_csrf_cookie
    
    
    @ensure_csrf_cookie
    def login(request):
        pass
    

      

    # 上传文件
    
    # urls.py
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    urlpatterns = [
        url(r'^admin/', admin.site.urls),   
        url(r'^ajax_file/', views.ajax_file),
        url(r'^form_file/', views.form_file),  
    ]
    
    
    # views.py
    def form_file(request):
        if request.method == 'POST':
            file_obj = request.FILES.get('file')
            with open(file_obj.name,'wb') as f:
                for i in file_obj.chunks():  # 使用chunks()函数可以一点一点上传
                    f.write(i)
            return HttpResponse('上传成功')
    
        return render(request,'form_file.html')
    
    
    def ajax_file(request):
    
        file_obj = request.FILES.get('f1')
        with open(file_obj.name,'wb') as f:
            for i in file_obj.chunks():
                f.write(i)
        return HttpResponse('上传成功')
    	
    	
    # form_file.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
    </head>
    <body>
    {#-------------------使用form表单上传文件-----------------#}
    <form action="" method="post" enctype="multipart/form-data">  # 需要指定enctype = 'multipart/form-data',不然默认的是下面的,会把我们上传的文件以键值对的形式(和url类似)拼接,然后放到请求体中
    {#<form action="" method="post" enctype="application/x-www-form-urlencoded">#}
        {% csrf_token %}
        <input type="file" name="file">
        <button>上传</button>
    </form>
    
    <hr>
    {#--------------------使用ajax上传文件--------------------------#}
    <h2>ajax上传文件</h2>
    <input type="file" name="file" id="f1">
    <button id="b1">上传</button>
    
    
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script>
        $("#b1").click(function () {
            var formData = new FormData();
            formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
            formData.append("f1", $("#f1")[0].files[0]);    {#  $("#f1")[0] 把jquery对象变为js对象#}
            $.ajax({
                url: "/ajax_file/",         {# 转向ajax_file路径,向这个路径发送请求 #}
                type: "POST",
                processData: false,  // 告诉jQuery不要去处理发送的数据
                contentType: false,  // 告诉jQuery不要去设置Content-Type请求头
                data: formData,
                success: function (data) {
                    console.log(data)
                }
            })
    
        })
    
    </script>
    </body>
    </html>
    
    
    
    
    
    # 使用json发送字符串
    
    def ajax_test(request):
        print(request.POST)
        print(request.POST.get('name'))
        print(request.POST.get('hobby'),type(request.POST.get('hobby')))
        d = {'status':0,'msg':''}
    
        # return HttpResponse(json.dumps(d))
        return JsonResponse(d)      # JsonResponse直接以json格式发送字典
    

      

      # 用户名注册,从数据库匹配用户名是否存在,如果存在提示,不存在注册

    # 用户名注册,从数据库匹配用户名是否存在,如果存在提示,不存在注册
    
    # views.py
    def reg(request):
        ret = {'status': 0, 'msg': ''}
        if request.is_ajax():
            name = request.POST.get('username')
            is_exist = models.UserInfo.objects.filter(username=name)
            if is_exist:
                ret['msg'] = '用户名已存在'
                ret['status'] = 1			
            else:
                ret['msg'] = '用户名可以使用'
            return JsonResponse(ret)
        return render(request, 'reg.html')
    	
    # reg.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="x-ua-compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>Title</title>
    </head>
    <body>
    <input type="text" id="i1"><span style="color: red"></span>
    <button id="b1">点击</button>
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
    <script src="/static/ajax_setup.js"></script>
    <script>
        $("#i1").blur(function () {		   <!-- i1失焦时,发送ajax请求-->
            var _this = $(this);
            $.ajax({
                url: '/reg/',
                type: 'post',
                data: {'username': $("#i1").val()},
                success: function (res) {
                    console.log(res);
    
                    if (res.status != 0) {
                        _this.next().text(res.msg);		<!--next指的是下一个标签-->
                    }
                }
            })
        });
        $("#i1").focus(function () {	<!-- i1聚焦时,清空span标签的内容-->
            $(this).next().text('')		<!-- input标签改变文本内容使用 .val(文本内容)   span标签改变文本内容 .text(文本内容)-->
        })
    
    </script>
    </body>
    </html>
    

    # 使用ajax的方式删除班级对象,当点击删除按钮时,通过ajex把班级对象的id传给后端,然后后端在数据库中删除这个班级对象,将成功的结果返回给ajax,然后前端删除该班级标签          

    # 使用ajax的方式删除每个班级对象
    
    
    # html文件
    <div class="table-responsive">
        <table class="table table-striped">
            <thead>
            <tr>
                <th>序号</th>
                <th>ID</th>
                <th>班级</th>
                <th>操作</th>
            </tr>
            </thead>
            <tbody>
            {% for class in class_list %}
                <tr data_id={{ class.id }}>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ class.id }}</td>
                    <td>{{ class.name }}</td>
                    <td>
                        <span class="btn btn-danger btn-sm ">
                                                    <i class="fa fa-trash-o fa-fw"></i>删除
                                                </span>
                        <a class="btn btn-success btn-sm" href="/edit_class/?id={{ class.id }}">
                            <i class="fa fa-edit fa-fw"></i>编辑
                        </a>
                    </td>
                </tr>
            {% empty %}
                <tr>
                    <td colspan="4" style="text-align: center">没有数据</td>
                </tr>
            {% endfor %}
            </tbody>
        </table>
    </div>
    
    
    
    <!--使用sweetalert插件,可以显示弹窗-->
    <script src="/static/plugins/dist/sweetalert.min.js"></script>
    <link rel="stylesheet" href="/static/plugins/dist/sweetalert.css">
    <!--jquery也用的到-->
    <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
    
    <script>
        $(".btn-danger").on("click", function (event) {
            _this = $(this);
            swal({
                    title: "你确定要删除吗?",
                    text: "删除可就找不回来了哦!",
                    type: "warning",
                    showCancelButton: true,
                    confirmButtonClass: "btn-danger",
                    confirmButtonText: "删除",
                    cancelButtonText: "取消",
                    closeOnConfirm: false
                },
                function () {
                    {#var deleteId = _this.parent().parent().attr('data_id'); 测试用#}
    
                    $.ajax({
                        url: "/del_class/",
                        type: "post",
                        data: {"id": deleteId},
                        success: function (data) {
                            if (data.status === 1) {
                                console.log(deleteId);
                                console.log($(this), 'ajax中的this');
                                {#<!--#}
                                {#w.fn.init [{…}]#}
                                {#0:{url: "/del_class/", type: "POST", isLocal: false, global: true, processData: true, …}#}
                                {#length:1#}
                                {#__proto__:Object(0)#}
                                {#ajax中的$(this)是ajax对象,包含了ajax中的参数;ajax外的$(this)才是我们选中的span对象(删除按钮)#}
                                {#-->#}
                                console.log(_this, 'ajax外的this');
                                {#<!--#}
                                {#w.fn.init [span.btn.btn-danger.btn-sm]#}
                                {#0:span.btn.btn-danger.btn-sm#}
                                {#length:1#}
                                {#__proto__:Object(0)-->#}
                                _this.parent().parent().remove()
                                {#$("[data_id=deleteId]").remove(); 测试用#}
                                {#不知道为什么这样用属性选择器不能找到,不是属性选择器的问题,是deleteId的问题,因为把deleteId换成一个具体的数字就行了,可能是属性选择器后面的属性不能用变量,因为我发现放数字和放变量data_id在pycharm上的颜色不同#}
    
                                swal("删除成功!", "你可以准备跑路了!", "success");
                            } else {
                                swal("删除失败", "你可以再尝试一下!", "error")
                            }
                        },
    
                    });
    
                });
        })
    </script>
    
    # views 中del_class函数
    def del_class(request):
        del_class = request.POST.get('id')
        class_obj = models.Class.objects.get(id=del_class)
        class_obj.delete()
        data = {}
        data['status'] = 1
        return JsonResponse(data)
    

      

  • 相关阅读:
    关于回溯与招聘市场
    关于回溯与马
    关于回溯和后宫
    关于兔子
    关于递归和斐波那契数列
    关于递归和汉诺塔
    关于简单汉诺塔
    nodejs报错roll back,because of a error.node.js setup wizard ended prematurel
    fatal error C1859 意外的预编译头错误,只需重新运行编译器
    sqlserver2008 无法设置主体sa的凭据
  • 原文地址:https://www.cnblogs.com/perfey/p/9677307.html
Copyright © 2020-2023  润新知