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 序列化组件、批量出入、自定义分页器的更多相关文章

  1. Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数

    Django和Ajax 一.什么是Ajax AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”.即使用Javascript语 ...

  2. Django序列化组件与数据批量操作与简单使用Forms组件

    目录 SweetAlert前端插件 Django自带的序列化组件 批量数据操作 分页器与推导流程 Forms组件之创建 Forms组件之数据校验 Forms组件之渲染标签 Forms组件之信息展示 S ...

  3. DRF 序列化组件 序列化的两种方式 反序列化 反序列化的校验

    序列化组件 django自带的有序列化组件不过不可控不建议使用(了解) from django.core import serializers class Books(APIView): def ge ...

  4. Django序列化组件Serializers详解

    本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ...

  5. Django-choices字段值对应关系(性别)-MTV与MVC科普-Ajax发json格式与文件格式数据-contentType格式-Ajax搭配sweetalert实现删除确认弹窗-自定义分页器-批量插入-07

    目录 models 字段补充 choices 参数/字段(用的很多) MTV与MVC模型 科普 Ajax 发送 GET.POST 请求的几种常见方式 用 Ajax 做一个小案例 准备工作 动手用 Aj ...

  6. django----Sweetalert bulk_create批量插入数据 自定义分页器

    目录 一.Sweetalert使用AJAX操作 二.bulk_create 三.分页器 divmod 分页器组件 自定义分页器的使用 一.Sweetalert使用AJAX操作 ​ sweetalert ...

  7. 分页器,序列化组件,bulk_create,choices字段

    分页器 <!--前端--> {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} ...

  8. Django中数据传输编码格式、ajax发送json数据、ajax发送文件、django序列化组件、ajax结合sweetalert做二次弹窗、批量增加数据

    前后端传输数据的编码格式(contentType) 提交post请求的两种方式: form表单 ajax请求 前后端传输数据的编码格式 urlencoded formdata(form表单里的) ja ...

  9. (day56)八、删除框、批量创建、分页器组件

    目录 一.ajax结合sweetalert实现删除按钮的动态效果 二.bulk_create批量插入数据 三.自定义分页器 (一)手动推导 (二)自定义分页器 (1)模板 (2)用法 一.ajax结合 ...

随机推荐

  1. Envoy实现.NET架构的网关(五)集成Redis实现限流

    什么是限流 限流即限制并发量,限制某一段时间只有指定数量的请求进入后台服务器,遇到流量高峰期或者流量突增时,把流量速率限制在系统所能接受的合理范围之内,不至于让系统被高流量击垮.而Envoy可以通过e ...

  2. cm2 逆向分析

    目录 cm2 逆向分析 前言 查壳 逆向分析 encrypt函数 POC代码 cm2 逆向分析 前言 这是逆向实战之CTF比赛篇的第3篇,在这里我就不再讲的特别小白了,有些简单操作可能会略过. 查壳 ...

  3. JavaScript复习 1

    概括及使用方法: JavaScript编写规范 一般放在<head>-</head>中间 逐行被执行,越短越好 大小写敏感 语句是基本单位 通常以分号表示语句结束 多行语句可以 ...

  4. httprunner3源码解读(3)client.py

    源码目录结构 ApiResponse 这个类没啥好说的 class ApiResponse(Response): """ 继承了requests模块中的Response类 ...

  5. [Vue warn]: Unknown custom element: <sapn> - did you register the component correctly? For recursive components, make sure to provide the "name" option. found in ---> <Evaluate> at src/views/index/

    关于vue报错: [Vue warn]: Unknown custom element: <sapn> - did you register the component correctly ...

  6. sklearn模型保存与加载

    sklearn模型保存与加载 sklearn模型的保存和加载API 线性回归的模型保存加载案例 保存模型 sklearn模型的保存和加载API from sklearn.externals impor ...

  7. LeetCode刷题 字符串详解

    一.字符串常用的操作 1. string类 1.1 string的定义与初始化 1.1.1 string的定义 1.1.2 string的初始化 1.2 string的赋值与swap.大小操作.关系运 ...

  8. 如何保证redis中存放的都是热点数据

    当redis使用的内存超过了设置的最大内存时,会触发redis的key淘汰机制,在redis 3.0中有6种淘汰策略: noeviction: 不删除策略.当达到最大内存限制时, 如果需要使用更多内存 ...

  9. [第二章]c++学习笔记3(构造函数)

    成员函数的一种 (1)名字与类名相同,可以有参数,不能有返回值(void也不行) (2)作用是对对象初始化,如给成员变量赋初值 (3)如果定义类时没写构造函数,则编译器生成一个默认的无参数的构造函数( ...

  10. Python科普系列——类与方法(上篇)

    欢迎来到新的系列,up又开新坑了~~ 实际上,Python作为一门易用性见长的语言,看上去简单,却仍然有很多值得一说的内容,因此这个系列会把Python中比较有意思的地方也给科普一遍.而另一方面,关于 ...