ajax实现删除提醒(普通版、进阶版)ajax发送文件 核心参数值dataType 自定义分页器
ajax实现删除提醒(普通版、进阶版)ajax发送文件 核心参数值dataType 自定义分页器
图书管理系统
#图书管理系统
首页展示功能
1.在后端查全部的数据对象 返回一个展示页面 并把数据对象传给展示页面
2.展示页面查询出全部的数据对象,展示页面
添加图书功能
1.创建添加图书页面的urls views返回一个添加html页面
2.html页面获取输入的数据 传给后端
3.后端判断是post请求 把数据拿过来写入到数据库 并重定向展示页面
编辑图书功能
1.将用户要编辑的数据主键值发送给后端
2.后端查询出相应的数据对象并返回一个编辑页面
3.在该编辑页面展示出待编辑对象的原始数据
4.用户修改完数据发送给后端 post请求
5.后端获取并修改相应的数据
删除功能
1.用户想要删除的数据主键值发送给后端
2.后端拿到主键值直接删除
choices参数
-
多对多三种创建方式
1.全自动 models.ManyToManyField(to='Author') 2.纯手动 自己创建第三张关系表 不使用ManyToManyField字段 3.半自动 models.ManyToManyField(to='Author', through='' through_fileds=() )
-
MTV与MVC模型
# 主要用于描述web框架的主要结构 django自称为MTV框架 其实本质也还是MVC框架
-
ajax基本语法结构
# 异步提交 局部刷新 '''基于jQuery的版本(务必要先导入jQuery)''' $.ajax({ url:'', # 控制提交的路径 三种书写格式 type:'', # 控制提交的方法 get/post/put/delete/options... data:'', # 控制提交的数据(可有可无) success:function(args){ # 异步回调机制 } })
-
content-Type参数
content-Type在请求头中 用于标识数据的编码格式 django针对不同编码格式的数据处理策略有所不同 针对urlencoded格式 自动处理到request.POST中 针对formdata格式 自动区分普通数据和文件数据分别处理到request.POST与request.FILES 针对json格式 django后端不做任何的处理 直接放在request.body中
-
ajax发送json格式数据(言行合一)
$.ajax({ url:'', # 控制提交的路径 三种书写格式 type:'', # 控制提交的方法 get/post/put/delete/options... data:JSON.stringify(数据), # 控制提交的数据(可有可无) contentType:'application/json' success:function(args){ # 异步回调机制 } })
-
ajax实现删除二次提醒(普通版本)
-
ajax结合第三方插件sweetalert实现二次提醒(样式好看些)
-
ajax如何发送文件数据
-
ajax核心参数之dataType
-
django序列化组件(自带的)
-
自定义分页器(django自带一个分页器只不过不好用)
-
自定义分页器的固定使用方式
-
ajax实现删除二次提醒(普通版本)
#如果想使用ajax和后端做交互,就不要用以前的交互方式了 以前的a的href的get请求 #html页面 id标签不能重复 class可以重复 所以给删除一个class #标签支持自定义属性 普通版本 -------------------------------------------------------------------------------- #ajax删除页面 url(r'^del_book',views.delete_book) -------------------------------------------------------------------------------- #boo_show.html #删除标签# <a class="btn btn-danger btn-xs c1" delete_id="{{ book_obj.pk }}">删除</a> <!--标签既可以有默认的属性也可以有自定义的属性--> -------------------------------------------------------------------------------- {% block js %} <script> let $btn=$('.c1'); $btn.on('click',function () { var delete_id=$(this).attr('delete_id') //$(this)指的是当前操作对象 attr 拿某个标签内部属性 var $this=$(this) //语法可能有冲突 在这声明下面直接用 //1.先做提醒 let res=confirm('确定删除吗') if (res){ //2.点了确定 发送ajax请求 $.ajax({ url:'/del_book/', type:'post', data: {'delete_id':delete_id}, //传的参数 success:function (args) { alert(args) window.location.reload()//刷新页面 第一种方式但是会有问题 //js代码自动刷新 第二种方式 上面定义了$this=$(this) //删除当前操作对象的父标签的父标签 $this.parent().parent().remove() } }) }else { alert('不敢吧 !!') } }) </script> {% endblock %} -------------------------------------------------------------------------------- def delete_book(request): #判断当前请求是否是ajax请求 if request.is_ajax(): if request.method=='POST': delete_id=request.POST.get('delete_id') models.Book.objects.filter(pk=delete_id).delete() return HttpResponse('删除成功!!!!!!!')
-
ajax结合第三方插件sweetalert实现二次提醒(样式好看些)
//引入cdn sweetalert <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script> //删除按钮 <script> var $btn=$('.c1'); $btn.on('click',function () { var delete_id=$(this).attr('delete_id') var $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) { $this.parent().parent().remove(); swal(args, { icon: "success", }); } }) } else { swal("不敢删吧!!"); } }); }) </script>
-
ajax如何发送文件数据
文件数据<input type="file" id="d1"> 普通数据<input type="text" id="d2"> 普通数据<input type="text" id="d3"> <button id="b1">提交ajax</button> <script> $('#b1').click(function () { //1.先获取用户输入的数据 //1.1.ajax发送携带文件数据的请求,需要借助于内置对象FormData //1.2定义一个formdata对象 let formDataObj=new FormData() //2.往该对象中添加数据(普通数据,文本数据都可以添加) //2.1 格式 ('别名',获取数据的values) formDataObj.append('name',$('#d2').val()) formDataObj.append('pwd',$('#d3').val()) //文件数据有固定的语法格式 #记住 固定语法 // 先找到这个对象索引0 在点files[0] formDataObj.append('files',$('#d1')[0].files[0]); $.ajax({ url:'/ab_files/', type:'post', //发送文件需要额外配置的两个参数contentType,processData contentType: false, processData: false, data:formDataObj, success:function (args) { alert(args) } }) }) </script>
-
ajax核心参数之dataType.
#前后端交互 如果采用的是ajax,后端的返回值应使用字典样式(json格式的字符串) 当后端采用HttpResponse返回json格式数据到ajax异步回调函数默认情况下需要我们自己做反序列化 前端如果不想手动反序列化后端传过来的json格式数据,可以指定dataType:'JSON' 指定后 后端返回给前端的数据如果不是json格式的 他不会反序列化 会自动区分 # 以后推荐加上 增加程序兼容性
-
django序列化组件(自带的)
from django.core import serializers #serializers.serializer 直接可以把 queryset套数据对象 转换成json格式的列表套字典 字典里自动加来自于哪个应用下的那个表,主键值 ,表的字段用一个fields做一个字典嵌套 外键什么的也会放在一个字典里 res=serializers.serialize('json',books_queryset) return HttpResponse(res)
-
批量插入数据
如果大批量创建数据 for循环创建效率极慢 # 批量插入 推荐 #生成器表达式 生产一个new_obj_iter里面存放了好多好多对象 new_obj_iter=(models.Book(title='第%s本书'%i) for i in range(100000)) #批量插入bulk_create models.Book.objects.bulk_create(new_obj_iter) data_queryset=models.Book.objects.all() return render(request,'ab_bc.html',locals())
-
分页
#思路 1.前端传给后端要看第几页数据 后端获取请求的页数 2.后端定义页面显示多少数据 起始位置 终止位置 他们是有逻辑关系的 3.后端通过divmod 获取总共多少页 有余数+1 4.后端定义 一个变量=当前页数 判断当前选择的页数小于最小页的中间位置 让这个变量=最小页的中间位置 为了防止左面越界 右面的也设置 5.后端编写HTML代码 for循环 开始位置-5 结束为止+6 设置超链接 并且选择的列高亮显示 6.前端接受数据 for循环数据对象 取title 加上一个分页器bootstrap 引用后面的html代码 实现显示十页 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) current_page=request.GET.get('page',1)#获取页数 try: current_page=int(current_page) except Exception: current_page=1 per_page_num=10 #每页展示多少条 start_page=(current_page-1)*per_page_num #开始行数 end_page=per_page_num*current_page #结束行数 #他们三个规律为 start_page=(current_page-1)*per_page_num # 开始位置 = (页数-1)*每页展示多少条 # end_page=current_page*per_page_num # 结束为止=页数*每页展示多少条 all_data = models.Book.objects.all() all_page_num, more = divmod(len(all_data),per_page_num ) if more: all_page_num+=1 html='' xxx=current_page if current_page<6: xxx=6 if current_page>all_page_num-6: xxx=all_page_num-6 for i in range(xxx-5,xxx+6): if i==current_page: 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 data_queryset=all_data[start_page:end_page] return render(request,'ab_bc.html',locals())
自定义分页器
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
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 get_book(request):
book_list = models.Book.objects.all()
current_page = request.GET.get("page",1)
all_count = book_list.count()
page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
page_queryset = book_list[page_obj.start:page_obj.end]
return render(request,'booklist.html',locals())
使用-前端
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</div>
</div>
</div>