• Ajax以及crsf的校验


    JSON

    注意:json必须是双引号,不能是单引号,否则会报错。如:{“name":"json","sex":"男"}

     Ajax

     本质:是一种利用现有技术的新方法。具有局部刷新,异步请求的优点

    Ajax的语法:

    $('#btn').click(function () {
        $.ajax({
            url:'',//请求url,不写的话,默认是当前页面
            type:'POST', //请求方式,默认是get
            //data:提交给后端的数据
            data:{i1:$('#d1').val(),i2:$('#d2').val()},
            //回调函数
            success:function (data) {
                $('#d3').val(data)
                {#alert(typeof(data))#}
            }
        })
    })

    了解前后端传输数据的格式:

    1、from表单

    from表单的默认编码是application/x-www-form-urlencoded格式,django后端会将urlencoded格式的数据自动解析封装到request.POST对象中,

    如果编码设置为multipart/form-data,Django后端会将键值对封装在request.POST对象中,文件解析封装在request.FILES对象中。

     注意:from表单是无法发送json数据的

    2、Ajax

    ajax默认也是application/x-www-form-urlencoded编码.  参数contentType: 'application/json',将编码格式转化为json格式。

    ajax发送文件,需要利用内置FormData()对象,然后将键值对对象,文件对象添加到FormData对象中,将FormData对象发给后端,

    Django后端识别到FormData对象,会自动将里面键值对对象解析封装给request.POST,里面的文件数据解析封装给request.FILES对象。

    注意 :注意编码格式跟数据格式要保持一致

               Django后端是不会自动帮你处理json数据,需要自己通过request.body来获取二进制的json数据,再用json模块序列化

       发送文件需要将两个参数设置为false,分别是:processData: false, contentType: false,

    //ajax发送文件  
    $('#btn').on('click',function () { //新建FormData对象 let formdataobj=new FormData(); //添加键值对 formdataobj.append('username',$('#d1').val()) formdataobj.append('password',$('#d2').val())
    //添加文件对象 formdataobj.append('file',$('#d3')[0].files[0]) $.ajax({ url:'', type:'post', data:formdataobj, //禁止使用任何编码 processData: false, //禁止浏览器对你数据进行处理 contentType: false, success:function (args) { } }) })

     Django内置的serializers

    #导入serializers模块
    from django.core import serializers
    #拿到user表中所有的用户
    obj=models.User.objects.all()
    #调用模块下的方法进行序列化,第一个参数表示序列化后的数据类型
     ret=serializers.serialize('json',obj)

    自定义分页器的封装方法及使用

    一般自定义的插件或者接口,都会存放在django项目下新建的utils目录下

    class Pagination(object):
        def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
            """
            封装分页相关数据
            :param current_page: 当前页
            :param all_count:    数据库中的数据总条数
            :param per_page_num: 每页显示的数据条数
            :param pager_count:  最多显示的页码个数
            """
            try:
                current_page = int(current_page)
            except Exception as e:
                current_page = 1
    
            if current_page < 1:
                current_page = 1
    
            self.current_page = current_page
    
            self.all_count = all_count
            self.per_page_num = per_page_num
    
            # 总页码
            all_pager, tmp = divmod(all_count, per_page_num)
            if tmp:
                all_pager += 1
            self.all_pager = all_pager
    
            self.pager_count = pager_count
            self.pager_count_half = int((pager_count - 1) / 2)
        #@property装饰器的方法,就是把方法变成属性使用
        @property
        def start(self):
            return (self.current_page - 1) * self.per_page_num
    
        @property
        def end(self):
            return self.current_page * self.per_page_num
    
        def page_html(self):
            # 如果总页码 < 11个:
            if self.all_pager <= self.pager_count:
                pager_start = 1
                pager_end = self.all_pager + 1
            # 总页码  > 11
            else:
                # 当前页如果<=页面上最多显示11/2个页码
                if self.current_page <= self.pager_count_half:
                    pager_start = 1
                    pager_end = self.pager_count + 1
    
                # 当前页大于5
                else:
                    # 页码翻到最后
                    if (self.current_page + self.pager_count_half) > self.all_pager:
                        pager_end = self.all_pager + 1
                        pager_start = self.all_pager - self.pager_count + 1
                    else:
                        pager_start = self.current_page - self.pager_count_half
                        pager_end = self.current_page + self.pager_count_half + 1
    
            page_html_list = []
            # 添加前面的nav和ul标签
            page_html_list.append('''
                        <nav aria-label='Page navigation>'
                        <ul class='pagination'>
                    ''')
            first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
            page_html_list.append(first_page)
    
            if self.current_page <= 1:
                prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
            else:
                prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
    
            page_html_list.append(prev_page)
    
            for i in range(pager_start, pager_end):
                if i == self.current_page:
                    temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
                else:
                    temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
                page_html_list.append(temp)
    
            if self.current_page >= self.all_pager:
                next_page = '<li class="disabled"><a href="#">下一页</a></li>'
            else:
                next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
            page_html_list.append(next_page)
    
            last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
            page_html_list.append(last_page)
            # 尾部添加标签
            page_html_list.append('''
                                               </nav>
                                               </ul>
                                           ''')
            return ''.join(page_html_list)
    自定义分页器

    后端引用:

    def page(request):
        #获取第一页
        current_page=request.GET.get('page',1)
        
        book_obj=models.Book.objects.all()
        #获取总页数
        book_all=book_obj.count()
        #获取分页器对象
        pagination=Pagination(all_count=book_all,current_page=current_page,per_page_num=10)
        #调用分页器对象中的start、end属性,就查询结果进行切片处理
        book_list=book_obj[pagination.start:pagination.end]
        return render(request,'page.html',locals())

    前端引用:

    {% for i in book_list %}
          <p>{{ i.name }}</p>
    {% endfor %}
    //取消对pagination.page_html属性中的html代码的转义
    {{ pagination.page_html|safe }}

     csrf_token校验

    form表单的校验

     //直接在form标签后面添加  {% csrf_token %}
      <form method="post" action="">
            {% csrf_token %}
            <p><input  type="hidden"></p>
            <p>username:<input type="text" name="id"></p>
            <p>Password:<input type="password" name="passwd"></p>
            <p><input type="submit" value="提交" id="btn"></p>
        </form>

    Ajax的三种校验方法(注意:ajax不能是form表单内的按钮点击事件,否则无法校验)

    1、获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。

    2、利用模板的快捷书写方法(前后端分离的时候,就用不了)

    $('#b1').click(function () {
          $.ajax({
               url:'',
               type:'post',
               data:{'id':$('#d1').val(),'passwd':$('#d2').val(),
               //第一种方法:获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
                 "csrfmiddlewaretoken":$('[name=csrfmiddlewaretoken]').val()
               //  第二种方法:利用模版的快捷书写方法
                  "csrfmiddlewaretoken":'{{ csrf_token }}'
                    },
               success:function () {
                  }
              })
     })

    3、通用方法,引用一个js文件,具体使用方法:在html页面引用该js文件

    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);
        }
      }
    });

    csrf相关的装饰器

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    '''
    csrf_exempt: 不需要校验
    csrf_protect: 需要校验
    总结:这两个装饰器在CBV中使用中
        csrf_protect在CBV的三个方法中是通用的
        csrf_exempt: 只有加在dispatch方法上才有用
    '''
  • 相关阅读:
    Java自学第18天
    Java自学第二十三天
    2\8定律,大家都要加油
    C#学习之我见
    2020年8月4日Java学习日记
    2020年8月5日
    2020年8月6日Java学习日记
    2020年8月7日Java学习日记
    第七章:(1)Spring Boot启动原理
    第六章:(3)数据访问 之 整合MyBatis
  • 原文地址:https://www.cnblogs.com/nq31/p/13773578.html
Copyright © 2020-2023  润新知