• 之Ajax


    1.Ajax简介

    AJAX 不是新的编程语言,而是一种使用现有标准的新方法。

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

        AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。

    特点:

    异步请求,局部刷新

    2.局部刷新

    如果是from表单提交之后,如果验证失败会自动刷新页面

    使用Ajax能保证只刷新局部

    示例:

    url

    from  app01 import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('login/', views.login,name='login'),
        path('home/', views.home,name='home'),
    ]
    

    views

    from django.shortcuts import render,HttpResponse,redirect
    
    # Create your views here.
    
    
    def login(request):
    
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            uname = request.POST.get('username')
            pwd = request.POST.get('password')
    
            if uname == 'zbb' and pwd == '123':
                return HttpResponse('1')
            else:
                return HttpResponse('0')
    
    
    
    def home(request):
    
        return render(request,'home.html')
    

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    用户名: <input type="text" id="username">
    密码: <input type="password" id="password">
    <button id="sub">提交</button>
    
    <span class="error"></span>
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script>
            $('#sub').click(function () {
    
            var uname = $('#username').val();
            var pwd = $('#password').val();
    
    
            $.ajax({
                url:'{% url "login" %}',
                type:'post',
                data:{username:uname,password:pwd},
                success:function (res) {
                    if (res === '1'){
                        location.href = '/home/';
    
                    }else{
                        $('.error').text('用户名密码错误!');
                    }
    
                }
    
            })
    
        })
    </script>
    </html>
    

    home.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>登陆成功</h1>
    
    </body>
    
    </html>
    

    3.CSRF

    详述CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。攻击者通过HTTP请求江数据传送到服务器,从而盗取回话的cookie。盗取回话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。

    Django默认会禁止未标识 post请求

    login.html

    4.from请求设置

    中加入 {% csrf_token %}

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="" method="post">
        {% csrf_token %}
        用户名: <input type="text" id="username">
        密码: <input type="password" id="password">
        <input type="submit">
    
    </form>
    
    <span class="error"></span>
    </body>
    
    </html>
    

    5.Ajax请求设置

    第一种方法

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    用户名: <input type="text" id="username">
    密码: <input type="password" id="password">
    <button id="sub">提交</button>
    <span class="error"></span>
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script>
            $('#sub').click(function () {
    
            var uname = $('#username').val();
            var pwd = $('#password').val();
            var csrf = '{{ csrf_token }}'; //加在这里
    
    
            $.ajax({
                url:'{% url "login" %}',
                type:'post',
                data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},//发送出
                success:function (res) {
                    if (res === '1'){
                        location.href = '/home/'; // http://127.0.0.1:8000/home/
    
                    }else{
                        $('.error').text('用户名密码错误!');
                    }
    
                }
    
            })
    
        })
    </script>
    </html>
    

    第二种方法

    需要引入一个jquery.cookie.js插件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    用户名: <input type="text" id="username">
    密码: <input type="password" id="password">
    <button id="sub">提交</button>
    <span class="error"></span>
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
    <script>
            $('#sub').click(function () {
    
            var uname = $('#username').val();
            var pwd = $('#password').val();
    
    
    
            $.ajax({
                url:'{% url "login" %}',
                type:'post',
                data:{username:uname,password:pwd},
                headers:{
                    "X-CSRFToken":$.cookie('csrftoken'), 
                },
     //其实在ajax里面还有一个参数是headers,自定制请求头,可以将csrf_token加在这里,我们发contenttype类型数据的时候,csrf_token就可以这样加           
                success:function (res) {
                    if (res === '1'){
    
                        location.href = '/home/';
    
                    }else{
                        $('.error').text('用户名密码错误!');
                    }
    
                }
    
            })
    
        })
    </script>
    </html>
    

    6.网络请求安全解决

    常见的网络请求安全解决方法

    Cookies Hashing:每一个表单请求中都加入随机的Cookie,由于网站中存在XSS漏洞而被偷窃的危险。 
    HTTP refer:可以对服务器获得的请求来路进行欺骗以使得他们看起来合法,这种方法不能够有效防止攻击。 
    验证码:用户提交的每一个表单中使用一个随机验证码,让用户在文本框中填写图片上的随机字符串,并且在提交表单后对其进行检测。 
    令牌Token:一次性令牌在完成他们的工作后将被销毁,比较安全。
    

    7.文件上传

    请求头ContentType

        ContentType指的是请求体的编码类型,常见的类型共有3种:

    1 application/x-www-form-urlencoded

      这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 默认格式application/x-www-form-urlencoded 方式提交数据,ajax默认也是这个。请求类似于下面这样(无关的请求头在本文中都省略掉了):
    
    POST http://www.example.com HTTP/1.1
    Content-Type: application/x-www-form-urlencoded;charset=utf-8
    
    user=yuan&age=22   #这就是上面这种contenttype规定的数据格式,后端对应这个格式来解析获取数据,不管是get方法还是post方法,都是这样拼接数据,大家公认的一种数据格式,但是如果你contenttype指定的是urlencoded类型,但是post请求体里面的数据是下面那种json的格式,那么就出错了,服务端没法解开数据。
    

    2.multipart/form-data

    这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data,form表单不支持发json类型的contenttype格式的数据,而ajax什么格式都可以发,也是ajax应用广泛的一个原因
    

    3.application/json

    application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。

    form表单文件上传

    url

    path('upload/', views.upload,name='upload'),
    

    views

    def upload(request):
        if request.method == "GET":
            return render(request,'upload.html')
        else:
            print(request.POST)
            print(request.FILES)
            uname = request.POST.get("username")
            pwd = request.POST.get('password')
            file_obj = request.FILES.get('file')
            print(file_obj.name)
    
            with open(file_obj.name,'wb') as f:
                # for i in file_obj:
                #     f.write(i)
            #文件太大只有一行怎么办?
                for chunk in file_obj.chunks():
            #默认一次返回大小为经测试为65536B,也就是64KB,最大为2.5M,是一个生成器
                    f.write(chunk)
    
    
            return HttpResponse("ok")
    

    upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="" method="post" enctype="multipart/form-data">
    {#    告诉浏览器不要一起发送,要一段一段的发送,指定:ContentType ..指的是请求体的编码类型#}
         
        {% csrf_token %}
        用户名: <input type="text" name="username">
        密码: <input type="password" name="password">
        头像: <input type="file" name="file">
        <input type="submit">
        
    </form>
    </body>
    
    </html>
    

    Ajax文件上传

    upload.html

    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        用户名: <input type="text" name="username">
        密码: <input type="password" name="password">
        头像: <input type="file" name="file" multiple>
    {#    multiple  的意思是可以上传多个#}
        <button id ='sub'>提交</button>
        <span class='error'></span>
    
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
    <script>
            $('#sub').click(function () {
    
                var formdata = new FormData();
    
                var uname = $('#username').val();
                var pwd = $('#password').val();
    
                var file_obj = $('[type=file]')[0].files[0];
    
    
                formdata.append('username',uname);
                formdata.append('password',pwd);
                formdata.append('file',file_obj);
    
            $.ajax({
                url:'{% url "upload" %}',
                type:'post',
                data:formdata,
                processData:false,
                contentType:false,
                //固定语法 不得对数据加工,直接发送原生数据
                headers:{
                    "X-CSRFToken":$.cookie('csrftoken'),
                },
                success:function (res) {
    
                        $('.error').text('完成');
    
    
                }
    
            })
    
        })
    </script>
    </html>
    

    8.json数据交互

    json数据类型和python数据类型的对比

    JsonResponse对象

        JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。

    from django.http import JsonResponse
    
    response = JsonResponse({'foo': 'bar'})
    print(response.content)
    
    b'{"foo": "bar"}'
    

    class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)

        这个类是HttpRespon的子类,它主要和父类的区别在于:

        1.它的默认Content-Type 被设置为: application/json

        2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。

        3.json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。

    #如果这样返回,ajax还需要进行json解析
    #views.py
    return HttpResponse(json.dumps({"msg":"ok!"}))
    
    #index.html
    var data=json.parse(data)
    console.log(data.msg);
    

        使用HttpResponse对象来响应数据的时候,还可以通过content_type指定格式:

    return HttpResponse(json.dumps(data),content_type="application/json")
    
    

        前端调试窗口就可以看到这个类型

        img

        如果不写这个参数是这个类型:长得像json格式的字符串,当然也可以转换成json的

        img

        看下面这种,JsonResponse默认就是content_type="application/json"。

    #如果这样返回,两边都不需要进行json的序列化与反序列化,ajax接受的直接是一个对象
    #views.py
    from django.http import JsonResponse
    return JsonResponse({"msg":"ok!"})
    
    #index.html
    console.log(data.msg);
    
    

    urls

    path('jsontest/', views.jsontest,name='jsontest'),
    
    

    代码 views

    from django.http import JsonResponse
    import json
    def jsontest(request):
        """
        状态码;
            1000 : 登录成功
            1001 : 登录失败
    
        :param request:
        :return:
        """
    
        if request.method == 'GET':
            return render(request,'jsontest.html')
        else:
            username = request.POST.get('username')
            pwd = request.POST.get('password')
            ret_data = {'status':None,'msg':None}
            print('>>>>>',request.POST)
            #<QueryDict: {'{"username":"123","password":"123"}'>
            if username == 'zbb' and pwd == '123':
                ret_data['status'] = 1000  # 状态码
                ret_data['msg'] = '登录成功'
    
    
            else:
                ret_data['status'] = 1001  # 状态码
                ret_data['msg'] = '登录失败'
    
            # ret_data_json = json.dumps(ret_data,ensure_ascii=False)
    
            # return HttpResponse(ret_data_json,content_type='application/json')
             #ret_data = ['aa',22,'bb']  /如果是数组
                
            return JsonResponse(ret_data) #safe =Flaser
    
    

    jsontest.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
        用户名: <input type="text" id="username">
        密码: <input type="password" id="password">
    
        <button id="sub">提交</button>
        <span class="error"></span>
    
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
    
    
    <script>
    
        $('#sub').click(function () {
            var uname = $('#username').val();
            var pwd = $('#password').val();
    
            $.ajax({
                url:'{% url "jsontest" %}',
                type:'post',
    
    
                data:{username:uname,password:pwd},
                headers:{
    
                    "X-CSRFToken":$.cookie('csrftoken'),
                },
                success:function (res) {
                    {#console.log(res,typeof res); // statusmsg {"status": 1001, "msg": "登录失败"}#}
    
                    console.log(res,typeof res); //直接就是反序列化之后的了
    
                    if (res.status === 1000){
    
                        location.href = '/home/';
    
                    }else{
                        $('.error').text(res.msg);
                    }
    
                }
    
            })
    
        })
    
    
    
    </script>
    
    </html>
    
    

    9.补充一个SweetAlert插件

    下载地址 百度jq2

    https://github.com/lipis/bootstrap-sweetalert
    
    

    url

    path('chajian/', views.chajian)
    
    

    views

    def chajian(request):
        return render(request,'chajian.html')
    
    

    html

    {% load static %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap-theme.min.css' %}">
        <link rel="stylesheet" href="{% static 'bootstrap-sweetalert-master/dist/sweetalert.css' %}">
    </head>
    <body>
    
    <div>
        <button class="btn btn-danger">删除</button>
    </div>
    
    </body>
    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
    
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
    <script src="{% static 'bootstrap-sweetalert-master/dist/sweetalert.js' %}"></script>
    <script>
    
        $(".btn-danger").on("click", function () {
            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: "/delete_book/",
                        type: "post",
                        data: {"id": deleteId},
                        success: function (data) {
                            console.log(data,typeof data);
                            if (data === '1') {
                                swal("删除成功!", "你可以准备跑路了!", "success");
                            } else {
                                swal("删除失败", "你可以再尝试一下!", "error")
                            }
                        }
                    })
                });
        })
    </script>
    </html>
    
    
  • 相关阅读:
    java后台svg转成png
    Itext2.0.8 和freemarker导出pdf
    使用freemarker生成word、html时图片显示问题
    ITEXT5 Font 'd:SIMSUN.TTC' with 'Identity-H' is not recognized.
    IntelliJ Idea 2017 免费激活方法
    MySQL 索引
    怎样使用nat和桥接方式解决虚拟机联网问题
    【Linux】NAT模式下关于主机ping不通虚拟机的问题
    同一台服务器(电脑)运行多个Tomcat
    [shell基础]——cut命令
  • 原文地址:https://www.cnblogs.com/zdqc/p/11756110.html
Copyright © 2020-2023  润新知