zoukankan      html  css  js  c++  java
  • Ajax

    Ajax简介

    AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

    • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
    • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
    • AJAX局部刷新

    jQuery实现的ajax

    <script>
    //.shadow{position: fixed;left: 0;top: 0;right: 0;bottom: 0;background-color: black;opacity: 0.4;z-index: 999;}
     
    $("#m_add_ok").click(function(){
            $.ajax({
                        url: '/m_user_add/',  // 要提交的地址
                        type: 'POST',     // GET或POST,提交方式
                        //dataType:'JSON',
                        data: {           // 提交的数据
                             'name': $("#m_add_box input[name='name']").val(),
                                'gender':$("#m_add_box input[name='gender']:checked").val(),
                                'email':$("#m_add_box input[name='email']").val(),
                                'depart_id':$("#m_add_box select[name='depart_id']").val()
                        },
                        success: function(data){
                            // 当服务端处理完成后,返回数据时,该函数自动调用
                            // data=服务端返回的值 默认是字符串
                            // console.log(data);
                            // JSON.parse(字符串) => 对象
                            // JSON.stringify(对象) => 字符串
                            var data=JSON.parse(data) //如果上面写了dataType:'JSON'  就相当于把success函数的参数data字符串转化成json对象,这就不需要写了json.parse(data)
                            if(data.status){
                                location.reload();
                                // location.href='/user_list/';
                            }else{
                                $('#titlemsg').text(data.titlemsg);
                            }
                        }
                    })
            });
    </script>
    View Code

    一、jQuery.ajax()

    1、请求参数

    ######################------------data---------################
     
           data: 当前ajax请求要携带的数据,是一个json的object对象,ajax方法就会默认地把它编码成某种格式
                 (urlencoded:?a=1&b=2)发送给服务端;此外,ajax默认以get方式发送请求。
     
                 function testData() {
                   $.ajax("/test",{     //此时的data是一个json形式的对象
                      data:{
                        a:1,
                        b:2
                      }
                   });                   //?a=1&b=2
    ######################------------processData---------################
     
    processData:声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,
                 那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString()
                 ,最后得到一个[object,Object]形式的结果。
                 
    ######################------------contentType---------################
     
    contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。
                 用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,
                 比如contentType:"application/json",即向服务器发送一个json字符串:
                   $.ajax("/ajax_get",{
                  
                      data:JSON.stringify({
                           a:22,
                           b:33
                       }),
                       contentType:"application/json",
                       type:"POST",
                  
                   });                          //{a: 22, b: 33}
     
                 注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象
     
                 views.py:   json.loads(request.body.decode("utf8"))
     
     
    ######################------------traditional---------################
     
    traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]},
                  traditional为false会对数据进行深层次迭代; 
    View Code

    2、响应参数

    /*
     
    dataType:  预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数。
                默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;
                比如我们的服务器响应的content Type为json格式,这时ajax方法就会对响应的内容
                进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式
                的对象;转换失败就会触发error这个回调函数。如果我们明确地指定目标类型,就可以使用
                data Type。
                dataType的可用值:html|xml|json|text|script
                见下dataType实例
     
    */
    View Code

    二、jQuery.serialize()

    该函数主要根据用于提交的有效表单控件的name和value,将它们拼接为一个可直接用于表单提交的文本字符串,该字符串已经过标准的URL编码处理(字符集编码为UTF-8)。

    • jQuery 1.0 新增该函数。语法:jQueryObject.serialize()
    • 返回值:serialize()函数的返回值为String类型,返回将表单元素编码后的可用于表单提交的文本字符串。
    • 不在
      标签内的、没有name属性的、带有disabled属性的、没有被选中的表单控件不会被提交。
    • serialize()函数通常用于将表单内容序列化,以便通过AJAX方式提交。
    • serialize()函数用于序列化所有表单元素。$("form").serialize()
    • serialize()函数用于序列化部分表单元素。$(":text, select, :checkbox").serialize()
    def ajax_login(request):
        if request.method == 'GET':
            return render(request, 'login.html')
        else:
            import json
            ret = {'status': True,'msg': None}
            obj = LoginForm(request.POST)
            if obj.is_valid():
                print(obj.cleaned_data)
            else:
                # print(obj.errors) # obj.errors对象
                ret['status'] = False
                ret['msg'] = obj.errors
            v = json.dumps(ret)
            return HttpResponse(v)
     
     
    <body>
        <h1>用户登录</h1>
        <form id="f1" >
            {% csrf_token %}
            <p>
                <input type="text" name="user" />
            </p>
            <p>
                <input type="password" name="pwd" />
            </p>
     
            <a onclick="submitForm();">提交</a>
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function submitForm(){
                $('.c1').remove();
                $.ajax({
                    url: '/ajax_login/',
                    type: 'POST',
                    data: $('#f1').serialize(),// user=alex&pwd=456&csrftoen=dfdf\
                    dataType:"JSON",
                    success:function(arg){
                        console.log(arg);
                        if(arg.status){
     
                        }else{
                            $.each(arg.msg,function(index,value){
                                console.log(index,value);
                                var tag = document.createElement('span');
                                tag.innerHTML = value[0];
                                tag.className = 'c1';
                                $('#f1').find('input[name="'+ index +'"]').after(tag);
                            })
                        }
                    }
                })
            }
        </script>
    </body>
    View Code

    csrf跨站请求伪造

    Djagno官方文档中关于CSRF的内容

    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');
    
    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);
        }
      }
    });
    
    
    在html页面上通过导入该文件即可自动帮我们解决ajax提交post数据时校验csrf_token的问题,(导入该配置文件之前,需要先导入jQuery,因为这个配置文件内的内容是基于jQuery来实现的)
    View Code
    <body>
       
    <!--
    {% csrf_token %} 生成input框
    {{ csrf_token }} 生成随机字符串
    -->
       
        <form method="POST" action="/csrf1.html">
            {% csrf_token %}
            <input id="user" type="text" name="user" />
            <input type="submit" value="提交"/>
            <a id="a_sub" >Ajax提交</a>
        </form>
       
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
       
            $("#a_sub").click(function(){
                var user = $('#user').val();
                $.ajax({
                    url: '/csrf1.html',
                    type: 'POST',
                    //方式1:
                    data: { "user":user,'csrfmiddlewaretoken': $("[name='csrfmiddlewaretoken']").val()},
                    //方式2:
                    // data: { "user":user,'csrfmiddlewaretoken': '{{ csrf_token }}'},
                    success:function(arg){
                        console.log(arg);
                    }
       
                })
            });
       
        </script>
       
       
        <script src="/static/jquery.cookie.js"></script>
        <script>
            $("#a_sub").click(function(){
                var user = $('#user').val();
                $.ajax({
                    url: '/csrf1.html',
                    //方式3:放在请求头中
                    headers:{'X-CSRFToken': $.cookie('csrftoken')},
                    type: 'POST',
                    data: { "user":user},
                    success:function(arg){
                        console.log(arg);
                    }
       
                })
            });
    </script>
       
    </body>
    View Code
    JSON.parse():     用于将一个 JSON 字符串转换为 JavaScript 对象 
    eg:
    console.log(JSON.parse('{"name":"tom"}'));
    console.log(JSON.parse('{name:"tom"}')) ;   // 错误
    console.log(JSON.parse('[12,undefined]')) ;   // 错误
     
    JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。 
    eg:  console.log(JSON.stringify({'name':"tom"}));
    stringify与parse方法

    上传文件

    一、Ajax(FormData)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
    </head>
    <body>
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-8 col-md-offset-2">
                <h1 class="text-center">注册</h1>
                <form id="myform">  <!--这里我们不用form表单提交数据 知识单纯的用一下form标签而已-->
                    {% csrf_token %}
                    {% for form in form_obj %}
                        <div class="form-group">
                            <label for="{{ form.auto_id }}">{{ form.label }}</label>
                            {{ form }}
                            <span style="color: red" class="pull-right"></span>
                        </div>
                    {% endfor %}
                    <div class="form-group">
                        <label for="myfile">头像
                            {% load static %}
                            <img src="{% static 'img/default.png' %}" id='myimg' alt="" width="100" style="margin-left: 10px">
                        </label>
                        <input type="file" id="myfile" name="avatar" style="display: none" >
                    </div>
    
                    <input type="button" class="btn btn-primary pull-right" value="注册" id="id_commit">
                </form>
            </div>
        </div>
    </div>
    
    <script>
        $("#myfile").change(function () {
    
    
            //本地上传预览 方法1:
            
            // 文件阅读器对象
            // 1 先生成一个文件阅读器对象
            let myFileReaderObj = new FileReader();
            // 2 获取用户上传的头像文件
            let fileObj = $(this)[0].files[0];
            // 3 将文件对象交给阅读器对象读取
            myFileReaderObj.readAsDataURL(fileObj)  // 异步操作  IO操作
            // 4 利用文件阅读器将文件展示到前端页面  修改src属性
            // 等待文件阅读器加载完毕之后再执行
            myFileReaderObj.onload = function(){
                 $('#myimg').attr('src',myFileReaderObj.result)
            }
            
    
            //本地上传预览 方法2:
            /*    var obj = $(this)[0].files[0];
                    var v = window.URL.createObjectURL(obj);
                    $('#myimg').attr('src',v);
                    $('#myimg').load(function(){
                        window.URL.revokeObjectURL(v);
                    });
            */
    
        })
    
        $('#id_commit').click(function () {
            // 发送ajax请求     我们发送的数据中即包含普通的键值也包含文件
            let formDataObj = new FormData();
            // 1.添加普通的键值对
            {#console.log($('#myform').serializeArray())  // [{},{},{},{},{}]  只包含普通键值对#}
            $.each($('#myform').serializeArray(),function (index,obj) {
                {#console.log(index,obj)#}  // obj = {}
                formDataObj.append(obj.name,obj.value)
            });
            // 2.添加文件数据
            formDataObj.append('avatar',$('#myfile')[0].files[0]);
    
            // 3.发送ajax请求
            $.ajax({
                url:"",
                type:'post',
                data:formDataObj,
    
                // 需要指定两个关键性的参数
                contentType:false,
                processData:false,
    
                success:function (args) {
                    if (args.code==1000){
                        // 跳转到登陆页面
                        window.location.href = args.url
                    }else{
                        // 如何将对应的错误提示展示到对应的input框下面
                        // forms组件渲染的标签的id值都是 id_字段名
                        $.each(args.msg,function (index,obj) {
                            {#console.log(index,obj)  //  username        ["用户名不能为空"]#}
                            let targetId = '#id_' + index;
                            $(targetId).next().text(obj[0]).parent().addClass('has-error')
                        })
                    }
                }
            })
        })
        // 给所有的input框绑定获取焦点事件
        $('input').focus(function () {
            // 将input下面的span标签和input外面的div标签修改内容及属性
            $(this).next().text('').parent().removeClass('has-error')
        })
    </script>
    </body>
    </html>
    View Code

    二、伪Ajax上传文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
     
    <style>
     
        .avatar_con {
            height: 100px;
            width: 100px;
            position: relative;
     
        }
     
        .avatar_con iframe {
            display: none
        }
     
        .avatar_con img {
            height: 100%;
            width: 100%;
            border: 0;
            overflow: hidden;
            max-height: 100px;
        }
     
        .avatar_con #previewImg {
            border-radius: 50%;
            border: 1px solid #dddddd;
            padding: 3px;
            height: 96px;
            width: 96px;
        }
     
        .avatar_con #avatarImg {
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            opacity: 0;
            position: absolute;
            z-index: 102;
        }
        .avatar-avatar_con .text {
            position: absolute;
            left: 0;
            bottom: 0;
            text-align: center;
        }
     
    </style>
     
    <body>
     
    <h1>伪 Ajax上传文件</h1>
    <div class="avatar_con">
        <iframe id="upload_iframe" name="upload_iframe"></iframe>
        <form method="POST" action="/upload/" enctype="multipart/form-data" target="upload_iframe">
            <!--target和iframe的name 进行关联-->
            <!--别忘了 编码格式 enctype="multipart/form-data"-->
            {% csrf_token %}
            <img id="previewImg" src="/media/avatar/default.png">
            <div class="text">点击图片更换</div>
            <input id="avatarImg" name="avatar" type="file"/>
        </form>
    </div>
     
     
    <script src="http://code.jquery.com/jquery-1.12.3.min.js"></script>
    <script type="text/javascript">
        $(function () {
            bindChangeAvatar();
        });
     
        function bindChangeAvatar() {
            $('#avatarImg').change(function () {
                $(this).parent().submit();
     
                $('#upload_iframe').load(function () {
                    var con = this.contentWindow.document.body.innerText;
                    con = JSON.parse(con);
                    if (con.status) {
                        console.log(con.data);
                        $('#previewImg').attr('src', '/' + con.data);
                    }
     
                })
     
            })
        }
     
    </script>
     
    </body>
    </html>
    View Code

    三、原生Ajax上传文件

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
     
    <style>
     
        .avatar_con {
            height: 100px;
            width: 100px;
            position: relative;
     
        }
     
        .avatar_con iframe {
            display: none
        }
     
        .avatar_con img {
            height: 100%;
            width: 100%;
            border: 0;
            overflow: hidden;
            max-height: 100px;
        }
     
        .avatar_con #previewImg {
            border-radius: 50%;
            border: 1px solid #dddddd;
            padding: 3px;
            height: 96px;
            width: 96px;
        }
     
        .avatar_con #avatarImg {
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            opacity: 0;
            position: absolute;
            z-index: 102;
        }
        .avatar-avatar_con .text {
            position: absolute;
            left: 0;
            bottom: 0;
            text-align: center;
        }
     
    </style>
     
    <body>
     
     
    <h1>原生Ajax上传文件</h1>
    <div class="avatar_con">
            <label for="avatar">
            <img  id="previewImg" src="/media/avatar/default.png">
            <div class="text">点击图片更换</div>
            </label>
            <input onchange="bindChangeAvatar()" id="avatarImg" name="avatar" type="file"/>
     
    </div>
     
     
     
    <script>
     
    function bindChangeAvatar(){
     
        var formdata = new FormData();
        formdata.append("avatar",document.getElementById('avatarImg').files[0]);
        formdata.append("csrfmiddlewaretoken","{{ csrf_token }}");  //csrf
     
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function(){
            if(xhr.readyState == 4){
                var arg = JSON.parse(xhr.responseText);
                document.getElementById('previewImg').src='/' + arg.data
            }
        };
        xhr.open('POST','/upload/');
        /*xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        发post请求必须设置Content-Type,request.POST才有数据,并且已转换成字典,
        不然就要去request.body中取值还是字节 b'a=1&b=2'
        如果发送的是formdata 则不需要设置
        */
        xhr.send(formdata);
    }
     
    </script>
     
    </body>
    </html>
    View Code
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>首页</h1>
        <input type="text" id="i1" />
        +
        <input type="text" id="i2" />
        =
        <input type="text" id="i3" />
    
        <input type="button" id="btn1" value="jQuery Ajax" onclick="add1();" />
        <input type="button" id="btn2" value="原生Ajax" onclick="add2();" />
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function add1(){
                $.ajax({
                    url: '/add1/',
                    type: 'POST',
                    data: {'i1': $('#i1').val(),'i2': $('#i2').val()},
                    success:function(arg){
                        $('#i3').val(arg);
                    }
                })
            }
    
            function add2(){
                /*
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        alert(xhr.responseText);
                    }
                };
                xhr.open('GET','/add2/?i1=12&i2=19');
                xhr.send();
                */
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        alert(xhr.responseText);
                    }
                };
                xhr.open('POST','/add2/');
                xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
                /*发post请求必须设置Content-Type,request.POST才有数据,并且已转换成字典,不然就要去request.body中取值还是字节 b'a=1&b=2'
                * 如果发送的是formdata 则不需要设置
                * */
                xhr.send("i1=12&i2=19");
            }
        </script>
    </body>
    </html>
    get方式

    四、服务端处理上传文件

    # 配置文件:
    STATIC_URL = '/static/'
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static')
    ]
    
    AUTH_USER_MODEL = 'app01.UserInfo'
    
    # 与用户上传相关的配置
    MEDIA_ROOT= os.path.join(BASE_DIR, "media")
    MEDIA_URL = "/media/"
    
    # 路由中:
    from django.conf.urls import url
    from django.contrib import admin
    from app01 import views
    from django.views.static import serve
    from django.conf import settings
    
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^register/',views.register,name='reg'),
        url(r'^login/',views.login,name='login'),
    
        url(r"media/(?P<path>.*)$", serve, {"document_root": settings.MEDIA_ROOT}),
    
    ]
    
    # 视图中:
    import os
    from django.shortcuts import render,HttpResponse,redirect
    from app01.myforms import MyRegForm
    from app01 import models
    from django.http import JsonResponse
    import time
    # Create your views here.
    
    def register(request):
        form_obj = MyRegForm()
        if request.method == 'POST':
            back_dic = {"code": 1000, 'msg': ''}
            # 校验数据是否合法
            form_obj = MyRegForm(request.POST)
            # 判断数据是否合法
            if form_obj.is_valid():
                # print(form_obj.cleaned_data)  # {'username': 'jason', 'password': '123', 'confirm_password': '123', 'email': '123@qq.com'}
                clean_data = form_obj.cleaned_data  # 将校验通过的数据字典赋值给一个变量
                # 将字典里面的confirm_password键值对删除
                clean_data.pop('confirm_password')  # {'username': 'jason', 'password': '123', 'email': '123@qq.com'}
                # 用户头像
                file_obj = request.FILES.get('avatar')
                file_obj.name = "%s.%s" % (time.time(), file_obj.name.rsplit('.')[-1])
    
                """针对用户头像一定要判断是否传值 不能直接添加到字典里面去"""
                if file_obj:
                    clean_data['avatar'] = file_obj
                # 直接操作数据库保存数据
                models.UserInfo.objects.create_user(**clean_data)
                back_dic['url'] = '/login/'
            else:
                back_dic['code'] = 2000
                back_dic['msg'] = form_obj.errors
            return JsonResponse(back_dic)
        return render(request,'register.html',locals())
    
    
    def login(request):
        return render(request,'login.html')
    View Code

    五、models.py

    from django.db import models
    from django.contrib.auth.models import AbstractUser
    class UserInfo(AbstractUser):
        """
        用户信息
        """
        nid = models.AutoField(primary_key=True)
        telephone = models.CharField(max_length=11, null=True, unique=True)
        avatar = models.FileField(upload_to='avatars/%Y-%m', default="avatars/default.png")
        create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
     
        blog = models.OneToOneField(to='Blog', to_field='nid', null=True, on_delete=models.CASCADE)
     
        def __str__(self):
            return self.username
     
        class Meta:
            verbose_name = '用户信息'
            verbose_name_plural = '用户信息'
    View Code

    六、带form验证

    # 书写针对用户表的forms组件代码
    from django import forms
    from app01 import models
    
    
    class MyRegForm(forms.Form):
        username = forms.CharField(label='用户名', min_length=3, max_length=8,
                                   error_messages={
                                       'required': '用户名不能为空',
                                       'min_length': "用户名最少3位",
                                       'max_length': "用户名最大8位"
                                   },
                                   # 还需要让标签有bootstrap样式
                                   widget=forms.widgets.TextInput(attrs={'class': 'form-control'})
                                   )
    
        password = forms.CharField(label='密码', min_length=3, max_length=8,
                                   error_messages={
                                       'required': '密码不能为空',
                                       'min_length': "密码最少3位",
                                       'max_length': "密码最大8位"
                                   },
                                   # 还需要让标签有bootstrap样式
                                   widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                                   )
    
        confirm_password = forms.CharField(label='确认密码', min_length=3, max_length=8,
                                           error_messages={
                                               'required': '确认密码不能为空',
                                               'min_length': "确认密码最少3位",
                                               'max_length': "确认密码最大8位"
                                           },
                                           # 还需要让标签有bootstrap样式
                                           widget=forms.widgets.PasswordInput(attrs={'class': 'form-control'})
                                           )
        email = forms.EmailField(label='邮箱',
                                 error_messages={
                                     'required': '邮箱不能为空',
                                     'invalid': '邮箱格式不正确'
                                 },
                                 widget=forms.widgets.EmailInput(attrs={'class': 'form-control'})
                                 )
    
        # 钩子函数
        # 局部钩子:校验用户名是否已存在
        def clean_username(self):
            username = self.cleaned_data.get('username')
            # 去数据库中校验
            is_exist = models.UserInfo.objects.filter(username=username)
            if is_exist:
                # 提示信息
                self.add_error('username', '用户名已存在')
            return username
    
        # 全局钩子:校验两次是否一致
        def clean(self):
            password = self.cleaned_data.get('password')
            confirm_password = self.cleaned_data.get('confirm_password')
            if not password == confirm_password:
                self.add_error('confirm_password', '两次密码不一致')
            return self.cleaned_data
    View Code
    {% extends 'mybook/base.html' %}
    
    {% block title %}
        <title>图书管理系统</title>
    {% endblock %}
    
    {% block content %}
    
        <div class="container">
            <div class="row">
                <a href="/mybook/add_book/" class="btn btn-info">添加图书</a>
            </div>
        </div>
        <div class="container">
            <div class="row">
                <table class="table table-striped table-hover">
                    <thead>
                    <tr>
                        <th>书名</th>
                        <th>作者</th>
                        <th>出版社</th>
                        <th>出版日期</th>
                        <th>零售价</th>
                        <th>操作</th>
                    </tr>
                    </thead>
                    <tbody>
                    {% for book in book_list %}
                        <tr>
                            <td>{{ book.title }}</td>
                            <td>
                                {% for author in book.authors.all %}
                                    {% if forloop.last %}
                                        {{ author.name }}
                                    {% else %}
                                        {{ author.name }},
                                    {% endif %}
    
                                {% endfor %}
                            </td>
                            <td>{{ book.publish.name }}</td>
                            <td>{{ book.publishDate|date:"Y-m-d" }}</td>
                            <td>{{ book.price }}</td>
                            <td>
                                <button class="btn btn-sm btn-warning" data-toggle="modal" data-target="#myModal"
                                        data-whatever="{{ book.nid }}">编辑
                                </button>
                                <a href="/mybook/delete_book?id={{ book.nid }}&next_action={{ current_path }}" class="btn btn-sm btn-danger">删除</a>
                            </td>
                        </tr>
                    {% endfor %}
                    </tbody>
                </table>
            </div>
    
        </div>
    
        <div class="modal fade" id="myModal">
            <div class="modal-dialog">
                <div class="modal-content">
    
                    <div class="modal-header">
                        <button class="close" data-dismiss="modal">X</button>
                        <div class="modal-title">修改图书信息</div>
                    </div>
    
                    <div class="modal-body">
                        <form id="book_form">
                            {% csrf_token %}
                            <div class="form-group">
                                <input type="text" hidden name="book_nid" id="book_nid">
                                <label for="book">书名</label>
                                <input type="text" class="form-control" id="title" name="title"
                                       disabled>
                                <span class="label label-danger" id="msg_tittle"></span>
                            </div>
                            <div class="form-group">
                                <b style="margin-bottom: 5px;display: inline-block">出版社</b>
                                <select class="form-control" id="publisher" name="publisher">
                                    {% for publisher in publisher_list %}
                                        {% if publisher.nid == book_obj.publisher.nid %}
                                            <option value={{ publisher.nid }} selected>{{ publisher.name }}</option>
                                        {% else %}
                                            <option value={{ publisher.nid }}>{{ publisher.name }}</option>
                                        {% endif %}
                                    {% endfor %}
                                </select>
                                <span class="label label-danger"></span>
                            </div>
                            <div class="form-group">
                                <label for="publish_date">出版日期</label>
                                <input type="date" class="form-control" id="publish_date" name="publish_date">
                                <span class="label label-danger " id="msg_publish_date"></span>
                            </div>
                            <div class="form-group">
                                <label for="price">零售价</label>
                                <input type="number" class="form-control" id="price" name="price">
                                <span class="label label-danger " id="msg_price"></span>
                            </div>
                            <div class="form-group">
                                <b style="margin-bottom: 5px;display: inline-block">作者</b>
                                <select class="form-control" multiple id="authors" name="authors">
                                    {% for author in author_list %}
                                        {% if author in book_obj.authors.all %}
                                            <option value={{ author.nid }} selected>{{ author.name }}</option>
                                        {% else %}
                                            <option value={{ author.nid }}>{{ author.name }}</option>
                                        {% endif %}
    
                                    {% endfor %}
                                </select>
                                <span class="label label-danger " id="msg_author"></span>
                            </div>
                        </form>
                    </div>
    
                    <div class="modal-footer">
                        <button class="btn btn-primary" id="book_save">保存</button>
                        <button class="btn btn-primary" data-dismiss="modal">取消</button>
                    </div>
                </div>
            </div>
        </div>
    
    {% endblock %}
    
    {% block script %}
        <script>
            $(function () {
                $("li[class=active]").parent().children().eq(0).addClass("active").siblings().removeClass("active");
            });
            $('#myModal').on('show.bs.modal', function (event) {
                var button = $(event.relatedTarget);// 触发事件的按钮
                var book_id = button.data('whatever');// 解析出data-whatever内容
                $.ajax({
                    url: "/mybook/edit_book?book_id=" + book_id,
                    type: "GET",
                    contentType: false,
                    processData: false,
                    data: {},
                    success: function (data) {
                        //console.log(data);
                        //console.log(book_id);
                        $(".label-danger").html("");
                        $('#book_nid').val(book_id);
                        $('#title').val(data.title);
                        $('#price').val(data.price);
                        $('#publish_date').val(data.publish_date);
                        $('#publisher').val(data.publisher);
                        $('#authors').val(data.book_author);
                    }
                });
            });
            $("#book_save").click(function () {
                var formdata = new FormData();
                var request_data = $("#book_form").serializeArray();
    
                console.log(request_data);  //[Object, Object, Object, Object, Object, Object, Object, Object, Object]
    
    
                $.each(request_data, function (index, data) {
                    formdata.append(data.name, data.value);
                });
                $.ajax({
                    url: "/mybook/edit_book/",
                    type: "POST",
                    contentType: false,
                    processData: false,
                    data: formdata,
                    success: function (data) {
                        $(".label-danger").html("");
                        if (isNullObj(data.msg)) {
                            location.href = window.location.href; //"/mybook/index/";
                        } else {
                            $.each(data.msg, function (field, error_list) {
                                $('#' + field).html(error_list);
                            })
                        }
                    }
                })
            });
    
        </script>
    {% endblock %}
    模态框

    浏览器的同源策略

    • 跨域是因为浏览器的同源策略导致的,也就是说浏览器会阻止非同源的请求
    • 域名不同或者端口不同都属于非同源的
    • 浏览器只阻止表单以及ajax请求,并不会阻止src请求,所以cnd,图片等src请求都可以发

    解决跨域

    方式一:CORS跨域请求

    • CORS即Cross Origin Resource Sharing 跨域资源共享
    • 随着技术的发展,现在的浏览器可以支持主动设置从而允许跨域请求,即:跨域资源共享(CORS,Cross-Origin Resource Sharing),其本质是设置响应头,使得浏览器允许跨域请求。
    • 跨域请求还分为两种,一种叫简单请求,一种是复杂请求

    1、简单请求

    • HTTP方法是下列方法之一 : HEAD, GET,POST
    • HTTP头信息不超出以下几种字段 : Accept, Accept-Language, Content-Language, Last-Event-ID , Content-Type
    • 其中Content-Type只能是下列类型中的一个 : application/x-www-from-urlencoded , multipart/form-data , text/plain
    • 简单请求:一次请求
    • 简单请求:服务器设置响应头:Access-Control-Allow-Origin = '域名' 或 '*'

    2、复杂请求

    • 任何一个不满足上述要求的请求,即会被认为是复杂请求
    • 复杂请求:两次请求,在发送数据之前会先发一次请求用做“预检”,OPTIONS请求,只有“预检”通过后才再发送一次请求用于数据传输。

    3、关于“预检”

    • 请求方式:OPTIONS
    • “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息

    4、如何“预检”

    • 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过 Access-Control-Request-Method
    • 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过 Access-Control-Request-Headers

    5、ContentType

    • 请求头ContentType指的是请求体的编码类型,常见的类型共有3种:
    • application/x-www-form-urlencoded 这应该是最常见的 POST 提交数据的方式了。浏览器的原生表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。
    • multipart/form-data 这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让表单的 enctype 等于 multipart/form-data。
    • application/json 用来告诉服务端消息主体是序列化后的 JSON 字符串。

    方式二:Jsonp

    • Jsonp的实现原理是根据浏览器不阻止src请求来实现的,通过script标签的跨域特性来绕过同源策略。
    • JSONP的原型:创建一个回调函数,然后在远程服务上调用这个函数并且将JSON 数据形式作为参数传递,完成回调。
    • JsonP解决跨域只能发送get请求,并且实现起来需要前后端交互比较多。
    • 如果报错ALLOWED_HOSTS 需要在settings.py 中配置需要访问的域名 ALLOWED_HOSTS = ['http://www.s4.com']
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
    <input type="button" onclick="AjaxRequest()" value="跨域Ajax" />
    
    
    <div id="container"></div>
    
    <script src="jquery-1.8.2.min.js" type="text/javascript"></script>
        <script type="text/javascript">
            function AjaxRequest() {
                $.ajax({
                    url: 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403',
                    type: 'GET',
                    dataType: 'jsonp',
                    jsonp: 'callback',
                    jsonpCallback: 'list',
                    success: function (data) {
                        $.each(data.data,function(i){
                            var item = data.data[i];
                            var str = "<p>"+ item.week +"</p>";
                            $('#container').append(str);
                            $.each(item.list,function(j){
                                var temp = "<a href='" + item.list[j].link +"'>" + item.list[j].name +" </a><br/>";
                                $('#container').append(temp);
                            });
                            $('#container').append("<hr/>");
                        })
    
                    }
                });
            }
    </script>
    </body>
    </html>
    实例:Ajax跨域
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    
    </head>
    <body>
        <input type="button" value="获取用户列表" onclick="getUsers();" />
        <ul id="user_list">
    
        </ul>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            /*
            function getUsers(){
                var xhr = new XMLHttpRequest();
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        var content = xhr.responseText;
                        console.log(content);
                    }
                };
                xhr.open('GET','http://www.s4.com:8001/users/');
                xhr.send();
            }
            */
            //a = ['alex','eric','egon']
    
            /*
             function getUsers(){
                 var tag = document.createElement('script');
                tag.src = "http://www.s4.com:8001/users/?callback=bbb?sdd";
                document.head.appendChild(tag);
             }
    
            function bbb(arg){
                console.log(arg);
            }
            */
            function getUsers(){
                // XMLHttpRequest
                /*
                $.ajax({
                    url: 'http://www.s4.com:8001/users/?callback=bbb',
                    type: 'GET',
                    success:function(arg){
                        console.log(arg);
                    }
                })
                */
                // JSONP
                $.ajax({
                    url: 'http://www.s4.com:8001/users/',
                    type: 'GET',
                    dataType: 'JSONP',
                    jsonp: 'callback',
                    jsonpCallback: 'bbb'
                })
            }
    
            function bbb(arg){
                console.log(arg);
            }
    
    
        </script>
    </body>
    </html>
    jsonp.html
    import json
    from django.shortcuts import render,HttpResponse
    from django.core.handlers.wsgi import WSGIRequest
    
    from django.views import View
    
    def users(request):
        v = request.GET.get('callback')
        print('请求来了...')
        user_list = [
            'alex','eric','egon'
        ]
        user_list_str = json.dumps(user_list)
        temp = "%s(%s)" %(v,user_list_str,)
        print(temp)
        return HttpResponse(temp)
    
    def new_users(request):
        print(request.method)
        if request.method == "OPTIONS":
            obj = HttpResponse()
            obj['Access-Control-Allow-Origin'] = "*"
            obj['Access-Control-Allow-Methods'] = "DELETE"
            return obj
    
        obj = HttpResponse('asdfasdf')
        obj['Access-Control-Allow-Origin'] = "*"
        return obj
        # user_list = [
        #     'alex','eric','egon'
        # ]
        # user_list_str = json.dumps(user_list)
        # obj = HttpResponse(user_list_str)
        #
        # obj['Access-Control-Allow-Origin'] = "*"
        # return obj
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <input type="button" value="获取用户列表" onclick="getUsers();" />
        <ul id="user_list">
    
        </ul>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            function getUsers(){
                $.ajax({
                    url: 'http://www.s4.com:8001/new_users/',
                    type:"DELETE",
                    success:function(arg){
                        console.log(arg);
                    }
                })
            }
        </script>
    </body>
    </html>
    cors.html
    <button id="btn_one">点击我向JsonP1发送请求</button>
    <script>
        // 测试发送请求失败 跨域不能得到数据
        $('#btn_one').click(function () {
            $.ajax({
                url: "http://127.0.0.1:8000/jsonp1",
                type: "get",
                success: function (response) {
                    console.log(response)
                }
            })
        });
    
        function handlerResponse(response) {
            alert(response)
        };
    
        window.onload = function () {
            $("#btn_one").click(function () {
                let script_ele = document.createElement("script");
                script_ele.src = "http://127.0.0.1:8000/jsonp1?callback=handlerResponse";
                document.body.insertBefore(script_ele, document.body.firstChild);
            })
        }
    
    
    </script>
    JsonP测试前端代码
    class Test(APIView):
    
        def get(self, request):
            callback = request.query_params.get("callback", "")
            ret = callback + "(" + "'success'" + ")"
            return HttpResponse(ret)
    JsonP实现的后端代码

    添加响应头

    from django.middleware.security import SecurityMiddleware
    from django.utils.deprecation import MiddlewareMixin
    
    
    class MyCors(MiddlewareMixin):
    
        def process_response(self, request, response):
            response["Access-Control-Allow-Origin"] = "*"
            if request.method == "OPTIONS":
                response["Access-Control-Allow-Methods"] = "PUT, DELETE"
                response["Access-Control-Allow-Headers"] = "content-type"
            return response
    middlewares.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
        'middlewares.MyCors',
    ]
    settings.py
    <!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>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <script src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
    
    </head>
    <body>
    <div id="app">
    
    </div>
    <script>
        const app = new Vue({
            el: "#app",
            mounted(){
                axios.request({
                    url: "http://127.0.0.1:8000/demo/",
                    method: "POST",
                    data: {
                        "name": "Alex"
                    }
                }).then(function (data) {
                    console.log(data)
                })
            }
        })
    </script>
    
    </body>
    </html>
    demo.html

    基于cors实现AJAX请求

    简单请求 OR 非简单请求
    条件:
        1、请求方式:HEAD、GET、POST
        2、请求头信息:
            Accept
            Accept-Language
            Content-Language
            Last-Event-ID
            Content-Type 对应的值是以下三个中的任意一个
                                    application/x-www-form-urlencoded
                                    multipart/form-data
                                    text/plain
    
    注意:同时满足以上两个条件时,则是简单请求,否则为复杂请求
    
    
    简单请求和非简单请求的区别?
    简单请求:一次请求
    非简单请求:两次请求,在发送数据之前会先发一次请求用于做“预检”,只有“预检”通过后才再发送一次请求用于数据传输。
    
    
    关于“预检”
    - 请求方式:OPTIONS
    - “预检”其实做检查,检查如果通过则允许传输数据,检查不通过则不再发送真正想要发送的消息
    - 如何“预检”
         => 如果复杂请求是PUT等请求,则服务端需要设置允许某请求,否则“预检”不通过
            Access-Control-Request-Method
         => 如果复杂请求设置了请求头,则服务端需要设置允许某请求头,否则“预检”不通过
            Access-Control-Request-Headers
    cors说明

     

    补充一个SweetAlert插件示例

    SweetAlert : https://www.sweetalert.cn/guides.html

    点击下载Bootstrap-sweetalert项目

     $("#b55").click(function () {
            swal({
                        title: "你确定要删除吗?",
                        text: "删除可就找不回来了哦!",
                        type: "warning",
                        showCancelButton: true,  // 是否显示取消按钮
                        confirmButtonClass: "btn-danger",  // 确认按钮的样式类
                        confirmButtonText: "删除",  // 确认按钮文本
                        cancelButtonText: "取消",  // 取消按钮文本
                        closeOnConfirm: false,  // 点击确认按钮不关闭弹框
                        showLoaderOnConfirm: true  // 显示正在删除的动画效果
                    },
                    function () {
                        var deleteId = 2;
                        $.ajax({
                            url: "/delete_book/",
                            type: "post",
                            data: {"id": deleteId},
                            success: function (data) {
                                if (data.code === 0) {
                                    swal("删除成功!", "你可以准备跑路了!", "success");
                                } else {
                                    swal("删除失败", "你可以再尝试一下!", "error")
                                }
                            }
                        })
                    });
        })

    上面这个二次确认的动态框样式,你也可以直接应用到你的项目中

    提醒事项:

    1.上述的样式类部分渲染的样式来自于bootstrap中,所有建议在使用上述样式时,将bootstrap的js和css也导入了,这样的情况下,页面效果就不会有任何问题

    2.弹出的上述模态框中,可能字体会被图标掩盖一部分,可通过调整字体的上外边距来解决

    图片预览 

    定制上传按钮:

    <div
                            style="position: relative;display: inline-block;height: 50px;min- 300px;overflow: hidden;">
                        <div style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;z-index: 1000;border: 1px dotted #9d9d9d;color: #9d9d9d;line-height: 50px;padding-left: 15px;">
                            <i class="fa fa-cloud-upload" aria-hidden="true"></i>
                            <span>点击上传文件</span>
                        </div>
                        <input name="customer_excel" type="file" id="excelFile"
                               style="position: absolute;top: 0;left: 0;right: 0;bottom: 0;background-color: #333333;z-index: 1001;opacity: 0;filter:alpha(opacity=0);">
                    </div>
    
    
    $(function () {
                $('#excelFile').change(function (e) {
                    var fileName = e.currentTarget.files[0].name;
                    $(this).prev().find('span').text(fileName);
                })
            })
    上传文件按钮
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <form method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <div style="height: 100px; 100px;padding: 2px;border: 1px solid #dddddd;position: relative;">
                <img style="height: 100%; 100%;border: 0;overflow: hidden;border-radius: 50%;" id="previewImg"
                     src="/static/imgs/default.png">
                <input style="top: 0;left: 0;right: 0;bottom: 0;opacity: 0;position: absolute;z-index: 102;" id="avatarImg"
                       name="avatar_img" type="file" class="img-file"/>
            </div>
            <div>点击图片更换(<a href="#">撤销</a>)</div>
    
            <p>
                <input type="text" placeholder="用户名">
            </p>
            <p>
                <input type="text" placeholder="密码">
    
            </p>
        </form>
    </div>
    </body>
    </html>
    上传图片按钮

    预览

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <form method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <div style="height: 100px; 100px;padding: 2px;border: 1px solid #dddddd;position: relative;">
                <img style="height: 100%; 100%;border: 0;overflow: hidden;border-radius: 50%;" id="previewImg"
                     src="/static/imgs/default.png">
                <input style="top: 0;left: 0;right: 0;bottom: 0;opacity: 1;position: absolute;z-index: 102;" id="avatarImg"
                       name="avatar" type="file" class="img-file"/>
            </div>
            <div>点击图片更换(<a href="#">撤销</a>)</div>
    
            <p>
                <input type="text" placeholder="用户名">
            </p>
            <p>
                <input type="text" placeholder="密码">
            </p>
            <input type="submit" value="提交">
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            $(function () {
                bindChangeAvatar1();
            });
    
            function bindChangeAvatar1() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    var blob = window.URL.createObjectURL(file_obj);
                    document.getElementById('previewImg').src = blob;
                    $('#previewImg').load(function () {
                        window.URL.revokeObjectURL(blob);
                    })
                })
            }
        </script>
    </div>
    </body>
    </html>
    预览方式一
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <form method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <div style="height: 100px; 100px;padding: 2px;border: 1px solid #dddddd;position: relative;">
                <img style="height: 100%; 100%;border: 0;overflow: hidden;border-radius: 50%;" id="previewImg"
                     src="/static/imgs/default.png">
                <input style="top: 0;left: 0;right: 0;bottom: 0;opacity: 1;position: absolute;z-index: 102;" id="avatarImg"
                       name="avatar" type="file" class="img-file"/>
            </div>
            <div>点击图片更换(<a href="#">撤销</a>)</div>
    
            <p>
                <input type="text" placeholder="用户名">
            </p>
            <p>
                <input type="text" placeholder="密码">
            </p>
            <input type="submit" value="提交">
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            $(function () {
                bindChangeAvatar2();
            });
    
            function bindChangeAvatar2() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    var reader = new FileReader();
                    reader.readAsDataURL(file_obj);
                    reader.onload = function (e) {
                        $('#previewImg')[0].src = this.result;
                    };
                })
            }
        </script>
    </div>
    </body>
    </html>
    预览方式二
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
        <form method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <div style="height: 100px; 100px;padding: 2px;border: 1px solid #dddddd;position: relative;">
                <img style="height: 100%; 100%;border: 0;overflow: hidden;border-radius: 50%;" id="previewImg"
                     src="/static/imgs/default.png">
                <input style="top: 0;left: 0;right: 0;bottom: 0;opacity: 1;position: absolute;z-index: 102;" id="avatarImg"
                       name="avatar" type="file" class="img-file"/>
            </div>
            <div>点击图片更换(<a href="#">撤销</a>)</div>
    
            <p>
                <input type="text" placeholder="用户名">
            </p>
            <p>
                <input type="text" placeholder="密码">
            </p>
            <input type="submit" value="提交">
        </form>
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            $(function () {
                bindChangeAvatar3();
            });
    
            function bindChangeAvatar3() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    var form = new FormData();
                    form.add('img_upload', file_obj);
                    $.ajax({
                        url: '',
                        data: form,
                        processData: false,  // tell jQuery not to process the data
                        contentType: false,  // tell jQuery not to set contentType
                        success: function (arg) {
                            // 给img标签设置src属性,预览
                        }
                    })
                })
            }
        </script>
    </div>
    </body>
    </html>
    预览方式三
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <div>
    
        <div style="height: 100px; 100px;padding: 2px;border: 1px solid #dddddd;position: relative;">
            <iframe style="display: none;" id="upload_iframe" name="upload_iframe"></iframe>
            <form method="POST" action="上传地址" enctype="multipart/form-data" target="upload_iframe">
                <img style="height: 100%; 100%;border: 0;overflow: hidden;border-radius: 50%;" id="previewImg"
                     src="/static/imgs/default.png">
                <input style="top: 0;left: 0;right: 0;bottom: 0;opacity: 1;position: absolute;z-index: 102;" id="avatarImg"
                       name="avatar" type="file" class="img-file"/>
            </form>
        </div>
        <div>点击图片更换(<a href="#">撤销</a>)</div>
    
        <form method="POST" enctype="multipart/form-data">
            {% csrf_token %}
            <p>
                <input type="text" placeholder="图片路径">
            </p>
            <p>
                <input type="text" placeholder="用户名">
            </p>
            <p>
                <input type="text" placeholder="密码">
            </p>
            <input type="submit" value="提交">
        </form>
    
        <script src="/static/jquery-1.12.4.js"></script>
        <script>
            $(function () {
                bindChangeAvatar4();
            });
    
            function bindChangeAvatar4() {
                $('#avatarImg').change(function () {
                    $(this).parent().submit();
                    $('#upload_iframe').load(function () {
                        var iframeContents = this.contentWindow.document.body.innerText;
                        iframeContents = JSON.parse(iframeContents);
                        if (iframeContents.status) {
                            $('#previewImg').attr('src', '/' + iframeContents.data);
                        }
                    })
    
                })
            }
        </script>
    </div>
    </body>
    </html>
    预览方式四

    参考兼容性:

    • https://developer.mozilla.org/zh-CN/docs/Web/API/URL/createObjectURL
    • https://developer.mozilla.org/zh-CN/docs/Web/API/FileReader
    • https://developer.mozilla.org/zh-CN/docs/Web/API/FormData
  • 相关阅读:
    day7
    11.3NOIP模拟赛
    codeforces 880E. Maximum Subsequence(折半搜索+双指针)
    11.2NOIP模拟赛
    bzoj1483: [HNOI2009]梦幻布丁(vector+启发式合并)
    day9
    codeforces 1006 F(折半搜索)
    codeforces 28D(dp)
    P2210 Haywire(A*)
    4800: [Ceoi2015]Ice Hockey World Championship(折半搜索)
  • 原文地址:https://www.cnblogs.com/bubu99/p/10258454.html
Copyright © 2011-2022 走看看