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)

  

原文地址:https://www.cnblogs.com/perfey/p/9677307.html