day11 序列化组件、批量出入、自定义分页器
day11 序列化组件、批量出入、自定义分页器
今日内容详细
- ajax实现删除二次提醒(普通版本)
- ajax结合第三方插件sweetalert实现二次提醒(样式好看些)
- ajax如何发送文件数据
- ajax核心参数之dataType
- django序列化组件(自带的)
- 自定义分页器(django自带一个分页器只不过不好用)
- 自定义分页器的固定使用方式
使用Ajax实现二次确认删除功能
# 使用ajax就不能使用下面的url,会造成冲突
<a href="{% url 'bd' book_obj.pk %}" class="btn btn-danger btn-xs">删除</a>  # 修改前
<a href="#" class="btn btn-danger btn-xs c1" delete_id="{{ book_obj.pk }}">删除</a>  # 修改后
 # // 标签既可以有默认的属性,也可以有自定义的属性,添加delete_id是可以获取主键id值
# views.py
def del_book(request):
    # 判断当前请求是否为ajax请求
    if request.is_ajax():
        if request.method == 'POST':  # 判断是否是ajax发来的post请求
            # 拿到ajax传到后端的data值
            delete_id = request.POST.get('delete_id')
            # 根据传过来的主键id删除数据
            models.Book.objects.filter(pk=delete_id).delete()
            return HttpResponse('删除成功!')
# book_list.html
{% block js %}
<script>
    var $btn = $('.c1'); // 找到c1标签
    // 绑定点击事件
    $btn.on('click',function () {
        var delete_id = $(this).attr('delete_id'); // 拿当前点击按钮中的delete_id属性
        var $this = $(this); // 给this设置一个变量
        {#alert(delete_id); // 试验是否拿到主键id#}
        // 做提醒效果
        let res = confirm('确定删除吗');
        // 判断是否为true
        if (res){ //true
            // 发送ajax请求
            $.ajax({
                url:'/del_book/',  // 向它发送请求
                type:'post',
                data:{'delete_id':delete_id},
                success:function (args) {
                    alert(args) ; // 接收到用户后端穿过来数据,代表已经删除成功
                    // 刷新页面
                    {#window.location.reload()#}
                    // js代码自动刷新
                    $this.parent().parent().remove()
                }
            })
        }else { // false
            return false
        }
    })
</script>
{% endblock %}
'''
总结:
1.先在a标签中添加一个自定义属性:delete_id={{book_obj.pk}},并且设置一个c1标签
2.找到c1标签,并且绑定一个点击事件
3.拿当前点击按钮中的delete_id属性
4.做提醒效果
5.判断是否为true
6.真的话:向后端发送ajax请求,并且其中把主键id传入到后端
7.在路由层和视图层开设出相应的函数
8.后端拿到ajax发来的主键id,根据主键id删除数据库数据,并给前端返回一个结果
9.前端拿到返回结果并打印,并刷新页面
'''
# 存在的问题:
        window.location.reload()
        当有多个页面时,使用上面的方法,会直接刷新到首页,会给用户造成不好的体验
# 解决:
        可以根据js代码自动删除,通过代码把tr标签删除
        var $this = $(this); // 给this设置一个变量
         // js代码自动刷新
         $this.parent().parent().remove()
试验url是否可以用反向解析
# 试验url是否可以用反向解析
    <script>
        var $btn = $('.c1');
        $btn.on('click',function () {
            $.ajax({
                url:'{% url "bl"  %}',
                type: 'post',
                data:'',
                succees:function () {
                }
            })
        })
    </script>
  [02/Dec/2021 16:58:16] "POST /del_book/ HTTP/1.1" 200 15   # 发送了一个post请求,证明是可以的
结合第三方模块实现二次确认删除功能
{% block js %}
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
    <script>
        var $btn = $('.c1'); // 找到c1标签
        // 绑定点击事件
        $btn.on('click',function (){
            var delete_id = $(this).attr('delete_id'); // 拿当前点击按钮中的delete_id属性
            var $this = $(this); // 给this设置一个变量
            swal({
              title: "确定要删除吗?",
              text: "要想好哦!",
              icon: "warning",
              buttons: true,
              dangerMode: true,
            })
            .then((willDelete) => {
              if (willDelete) {
                  // 向后端发送ajax请求
                  $.ajax({
                      url:'/del_book/',
                      type:'post',
                      data:{'delete_id':delete_id},
                      success:function (args) {
                          // js代码自动刷新
                          $this.parent().parent().remove();
                          {#window.location.reload();#}
                          swal(args, {
                                icon: "success",
                          }
                        );
                      }
                  })
              } else {
                swal("取消成功!");
              }
            });
        })
    </script>
{% endblock %}
第三方模块:https://sweetalert.js.org
ajax如何发送文件数据
<body>
文件数据<input type="file" id="i1">
普通数据<input type="text" id="i2">
普通数据<input type="text" id="i3">
<button id="b1">提交</button>
<script>
    $('#b1').on('click',function () {
        // 先获取输入框中用户的数据
        {#let i1Val = $('#i1').val();#}
        {#let i2Val = $('#i2').val();#}
        {#let i3Val = $('#i3').val();#}
        // ajax发送携带文件数据的请求,需要借助与内置对象FormData
        // 1.生成一个FormData对象
        let formDdatObj = new FormData();
        // 2.向该对象中添加数据(支持普通数据和文件数据)
        formDdatObj.append('name',$('#i2').val());
        formDdatObj.append('pwd',$('#i3').val());
        // 获取文件数据有固定的语法格式
        formDdatObj.append('file',$('#i1')[0].files[0]);
        // 发送ajax请求
        $.ajax({
            url:'/ab_file/',
            type:'post',
            // 发送文件需要额外配置的两个参数
            contentType:false,
            processData:false,
            data:formDdatObj,
            success:function () {
            }
        })
    })
</script>
</body>
dataType参数
"""前后端交互 如果采用的是ajax 那么后端的返回值应该使用字典(json格式)"""
# 结论:
    1、当后端采用HttpResponse返回json格式数据到ajax异步回调函数默认情况下需要我们自己做反序列化JSON.parse如果不想自己处理可以添加dataType:"JSON"
    2、如果后端是采用JsonResponse返回json格式数据则无需我们自己处理也不需要添加 # 返回的就是JSON格式数据
	3、dataType:"JSON"参数(加了也不影响)  # 处理JSON数据最好加上
# 以后推荐加上 增加程序兼容性
<button id="b1">提交</button>
<script>
    $('#b1').click(function () {
        $.ajax({
            url:'/ab_json/',
            type:'post',
            data:'',
            // 自动把后端返回的JSON格式数据序列化
            dataType:'JSON',
            success:function (args) {
                console.log(args);
                console.log(typeof args);
                // 反序列化
                {#let json_obj = JSON.parse(args);#}
                {#console.log(json_obj);#}
                {#console.log(typeof json_obj);#}
                {#console.log(json_obj.code)#}
            }
        })
    })
</script>
序列化模块
什么意思呢?
	就是我的前端想拿到由ORM得到的数据库里面的一个个用户对象,我的后端想直接将实例化出来的数据对象直接发送给客户端,那么这个时候,就可以用Django给我们提供的序列化方式
    def ser(request):
        #拿到用户表里面的所有的用户对象
        user_list=models.User.objects.all()
        #导入内置序列化模块
        from django.core import serializers
        #调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
        ret=serializers.serialize('json',user_list)
        return HttpResponse(ret)
# 拿到所有数据对象去JSON格式化网站格式化
格式化网站:https://www.bejson.com/

批量插入数据
# 批量插入数据有三种方法:
	一、循环插入  # 不推荐此法 效率极低
        循环创建十万本书籍数据
        def ab_bc(request):
            for i in range(100000):  # 不推荐此法 效率极低
                models.Book.objects.create(title='第%s本书'%i)
    二、利用生成器插入  #  如果对象很多的情况下 比较浪费空间
    	def ab_bc(request):
            new_obj_list = []
            for i in range(100000):
            仅仅是用类产生了对象 并没有操作数据库
            book_obj = models.Book(title='第%s本新的书'%i)  
    三、bulk_create方法:  # 推荐使用
        def ab_bc(request):
            new_obj_iter = (models.Book(title='第%s本新的书'%i) for i in range(100000))
            # 批量插入
            models.Book.objects.bulk_create(new_obj_iter)  # 用bulk_create方法批量插入
            # 查询所有
            data_queryset = models.Book.objects.all()
            return render(request,'ab_bc.html',locals())
        '''使用bulk_create方法可以大大减少操作的时间'''
分页器思路
前提准备:先使用bulk_create方法创建1000条书籍数据
完成分页器需要考虑的几个问题
    1.需要数据的总量
    2.需要定义每页展示多少条
    3.需要计算总共需要多少页
    4.需要推导出几个核心参数的数学关系
    5.需要后端生成html代码
    # 可以切片来完成
思路:
    1.获取用户想访问的页码,如果没有默认展示第一页,并做类型转换
    2.设置每页展示多少条数据,并设置切片的初始位置和终止位置
    3.根据设置的几个参数找数学规律,并把规律复制给切片的初始位置和终止位置的变量
    4.这一步就可以根据浏览器的?page=10,来实现展示多少页
    5.给pager.html加上bookstrap分页样式
    6.通过内置方法divmod,使所有的数据 / 每页展示多少条 ==  总页数
        # divmod(100,10)  返回(10,0) 100/10 返回整数和余数
    7.利用for循环渲染前端页面,并指定添加页码传入前端,前端引用变量名
    8.后端传输数据到前端必须转义,转义后所有的页码都显示在浏览器中。  # 但是页码太多,要求只展示11个页码
    9.通过for循环来控制展示多少页码  #  for i in range(current_page-5, current_page+6):
规律:
"""
下面需要研究current_page、per_page_num、start_page、end_page四个参数之间的数据关系
per_page_num = 10
current_page                start_page                  end_page
    1                           0                           10
    2                           10                          20
    3                           20                          30
    4                           30                          40
per_page_num = 5
current_page                start_page                  end_page
    1                           0                           5
    2                           5                           10
    3                           10                          15
    4                           15                          20
可以很明显的看出规律
start_page = (current_page - 1) * per_page_num
end_page =  current_page* per_page_num
设置每页展示10条数据,当页码为1的时候,切片的起始位置为0,终止位置为10。
页码为2的时候,切片的起始位置为10,终止位置为20。
依次切片下去,达成每页展示10条数据的效果
"""
分页器核心逻辑
views.py
from django.shortcuts import render, HttpResponse
from app01 import models
def pager(request):
    # 批量插入1000本书籍记录
    # new_obj_iter = (models.Book(title='第%s本书'%i) for i in range(1000))  # 现在并没有走数据库,只是一个生成器表达式
    # 批量插入
    # models.Book.objects.bulk_create(new_obj_iter)
    '*******************************分页器代码实现*****************************************'
    # 查询所有数据
    all_data = models.Book.objects.all()
    # 获取用户想访问的页码,如果没有默认展示第一页
    current_page = request.GET.get('page', 1)
    try:
        current_page = int(current_page)  # 做类型转换
    except Exception:
        current_page = 1
    # 设置每页展示10条数据
    per_page_num = 10
    # 需要对总数据进行切片操作 需要确定切片起始位置和终止位置
    start_page = (current_page - 1) * per_page_num     # 切片起始位置
    end_page = current_page * per_page_num             # 切片终止位置
    # 通过divmod内置函数计算多少页
    all_page_num, more = divmod(len(all_data), per_page_num)  # 用divmod方法,使所有的数据除于每页展示多少条
    if more:
        all_page_num += 1  # more是余数,余数有值就给总页数加一
    # print(all_page_num)  # 总页数700
    # 渲染前端页面
    html = ''
    xxx = current_page
    if current_page < 6:
        xxx = 6
    # 用当前页-5和当前页+6来控制显示的页码
    for i in range(xxx-5, xxx+6):
        # 当前页和访问页一致,会有高亮显示
        if current_page == i:
            # 生成页码
            tmp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
        else:
            tmp = '<li><a href="?page=%s">%s</a></li>' % (i, i)
        html += tmp  # 把页码都放入html里,在前端引用即可
    # 查询所有
    data_request = all_data[start_page:end_page]
    return render(request, 'pager.html', locals())
pager.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
     <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<!--把后端传入的数据展示到浏览器上-->
{% for book_obj in data_request %}
    <p>{{ book_obj.title }}</p>
{% endfor %}
<!--分页样式-->
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="?page=1" aria-label="Previous">
        <span aria-hidden="true">首页</span>
      </a>
    </li>
   	# 引用并创建页码
    {{ html | safe }}
    <li>
      <a href="?page={{ all_page_num }}" aria-label="Next">
        <span aria-hidden="true">尾页</span>
      </a>
    </li>
  </ul>
</nav>
</body>
</html>
day11 序列化组件、批量出入、自定义分页器的更多相关文章
- Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数
		Django和Ajax 一.什么是Ajax AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”.即使用Javascript语 ... 
- Django序列化组件与数据批量操作与简单使用Forms组件
		目录 SweetAlert前端插件 Django自带的序列化组件 批量数据操作 分页器与推导流程 Forms组件之创建 Forms组件之数据校验 Forms组件之渲染标签 Forms组件之信息展示 S ... 
- DRF   序列化组件  序列化的两种方式   反序列化   反序列化的校验
		序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ... 
- Django序列化组件Serializers详解
		本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ... 
- Django-choices字段值对应关系(性别)-MTV与MVC科普-Ajax发json格式与文件格式数据-contentType格式-Ajax搭配sweetalert实现删除确认弹窗-自定义分页器-批量插入-07
		目录 models 字段补充 choices 参数/字段(用的很多) MTV与MVC模型 科普 Ajax 发送 GET.POST 请求的几种常见方式 用 Ajax 做一个小案例 准备工作 动手用 Aj ... 
- django----Sweetalert bulk_create批量插入数据  自定义分页器
		目录 一.Sweetalert使用AJAX操作 二.bulk_create 三.分页器 divmod 分页器组件 自定义分页器的使用 一.Sweetalert使用AJAX操作  sweetalert ... 
- 分页器,序列化组件,bulk_create,choices字段
		分页器 <!--前端--> {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} ... 
- Django中数据传输编码格式、ajax发送json数据、ajax发送文件、django序列化组件、ajax结合sweetalert做二次弹窗、批量增加数据
		前后端传输数据的编码格式(contentType) 提交post请求的两种方式: form表单 ajax请求 前后端传输数据的编码格式 urlencoded formdata(form表单里的) ja ... 
- (day56)八、删除框、批量创建、分页器组件
		目录 一.ajax结合sweetalert实现删除按钮的动态效果 二.bulk_create批量插入数据 三.自定义分页器 (一)手动推导 (二)自定义分页器 (1)模板 (2)用法 一.ajax结合 ... 
随机推荐
- Envoy实现.NET架构的网关(四)集成IdentityServer4实现OAuth2认证
			什么是OAuth2认证 简单说,OAuth 就是一种授权机制.数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据.系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使 ... 
- udev 使用方法
			原文地址 http://blog.163.com/againinput4@yeah/blog/static/122764271200962305339483/ 最近有在研究SD卡设备节点自动创建及挂载 ... 
- JAVA笔记3__字符串String类/对象一对一关联
			import java.lang.String; import java.util.Scanner; public class Main { public static void main(Strin ... 
- MSSQL SQL注入 总结
			0x00 MSSQL 基础 MSSQL系统自带库和表 系统自带库 MSSQL安装后默认带了6个数据库,其中4个系统级库:master,model,tempdb和msdb:2个示例库:Northwind ... 
- 该虚拟机似乎正在使用中。如果该虚拟机未在使用,请按“获取所有权(T)”按钮获取它的所有权
			问题 打开虚拟机镜像时报 VMware该虚拟机似乎正在使用中.如果该虚拟机未在使用,请按"获取所有权(T)"按钮获取它的所有权 解决方法 在你安装的镜像文件目录下找到后缀为.vmx ... 
- forceUpdate() & set
			前言 在开发过程中,我们时常会遇到这样一种情况:当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,是不会更新视图的. 根据官方文 ... 
- [LINUX] Arch Linux 硬盘拷贝式装系统+新增 home 分区
			目录 前言 1. 实操 1.1 整个磁盘拷贝 1.2 创建 home 分区 1.3 修改 fstab 实现自动挂载 2. 涉及到的知识点 2.1 fstab 2.2 dd 命令 2.3 fdisk 命 ... 
- Linux mem 2.6 Rmap 内存反向映射机制
			文章目录 1. 简介 2. 匿名内存 Rmap 的建立 2.1 fork() 2.2 do_page_fault() 3. 文件内存 Rmap 的建立 3.1 fork() 3.2 do_page_f ... 
- C# | VS2019连接MySQL的三种方法以及使用MySQL数据库教程
			本文将介绍3种添加MySQL引用的方法,以及连接MySQL和使用MySQL的教程 前篇:Visual Studio 2019连接MySQL数据库详细教程 \[QAQ \] 第一种方法 下载 Mysql ... 
- Typora下载安装教程
			Typoa下载和安装 Typora---程序员记事本!!! 这里我们选择Typora作为我们的编辑器,功能的强大需要各位自己去体会. Typora下载地址 点击链接打开,然后选择Download! 根 ... 
