Ajax介绍
Ajax:异步提交,局部刷新
发送请求:
1.浏览器输入网址
2.form表单
3.a标签
4.ajax ===> POST/GET
Ajax:
1.并不是一门新的编程语言,而是一门新的标准方法(类似于装饰器)
2.能够在不刷新页面的前提下,与服务器交换数据刷新部分内容
Ajax基本格式
前端基本格式
$('.btn').click(function () {
$.ajax({
// 1.指定朝那个后端发数据
url: '',
// 2.请求方式
type: 'post',
// 补充1
dataType:'post' // 针对后端httpresponse发送过来的数据自动反序列化
// 3.发送的数据
data: {'d1': $('#d1').val(), 'd2': $('#d2').val()},
// 4.回调函数:当后端给你返回结果的时候会自动触发 args接受后端的返回结果
success: function (args) {
let dict = JSON.parse(args)
alert(dict)
$('#d3').val(dict.d3)
console.log(typeof (dict))
}
})
})
后端处理:
if request.method == 'POST':
d1 = request.POST.get('d1')
print(d1)
d2 = request.POST.get('d2')
d3 = int(d1) + int(d2)
d3_dict = {'d3': d3}
return HttpResponse(json.dumps(d3_dict))
前后端传输数据基本文件格式(ContentType)
1.get/post请求的差别
get请求的数据放在网址的/?后面进行字符串拼接传给后端
post请求的数据会放在请求体中传给后端
2.前后端交互的三种文件格式
针对form表单
urlencoded
默认的传输格式
无论是在请求体和请求头数据格式都是类似:username=123&passowrd=456
后端针对拿到符合urlencoded的数据格式会自动处理后封装到request.POST对象中
formdata
formdata支持文件和数据的传输
会自动去问文件和数据,将符合urlencoded的数据放到request.POST对象中
文件格式会放到FILES中
json
针对ajax
默认也是urlencoded传输
数据格式也是类似:username=123&passowrd=456
将符合urlencoded的数据格式处理后封装到request对象之中
ajax发送json数据
1.request对象补充.
request.is_ajax()
用来判断当前发送请求的方式是否为ajax
是:True 否:False
2.ajax发送json数据参数
contentType:'application/json'
如果要发送json格式的数据,必须要保证发送的数据和指定的数据类型一致
3.ajax发送的json数据存储在request.body中
所有要在body中获取
<script>
$('#d1').click(function () {
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'username':'jason','age':25}),
contentType:'application/json',
success:function () {
}
})
})
</script>
json_bytes = request.body
json_str = json_bytes.decode('utf-8')
json_dict = json.loads(json_str)
# json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化
json_dict = json.loads(json_bytes)
ajax发送文件数据
1.ajax发送文件数据需要借用js内置对象FormData
2.即可以接受文件数据,也可以皆有urlencoded格式的数据
3.发送文件必须指定两个参数
1.contentType:'false' //不需要使用任何编码格式,django后端会自动识别
2.processType:'false //告诉浏览器不要对数据进行任何加工
<body>
username:<input name='user' type="text" id="d1">
password:<input type="text" name="password" id="d2">
<input type="file" name="file" id="d3">
<button id="d4">提交ajax</button>
<script>
$('#d4').on('click',function (){
let formDateObj = new FormData();
formDateObj.append('username', $('#d1').val());
formDateObj.append('password', $('#d2').val());
formDateObj.append('file', $('#d3')[0].files[0]);
$.ajax(
{
url:'',
type:'post',
data:formDateObj,
contentType:false,
processData:false,
success:function (arg){
}
}
)
})
</script>
def ab_file(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return render(request, 'ab_file.html')
django自带的序列化组件
针对前后端分离的开发项目,后端一般只要返回列表套字典的数据格式给前端就可,不需要进一步进行前端操作
from djaong.core import serializers
def ab_ser(request):
user_queryset = models.User.objects.all()
// 也可以手动操作
'''
user_list = []
for user_obj in user_queryset:
user = {name:'...',.......}
user_list.append(user)
'''
res = serializers.serialize('json',user_queryset) // 自动转化为序列化的json格式
return HttpResponse(res)
批量插入数据
1.for循环
2.bulk_create() 速度快,能够大大减少数据插入的时间
1.for
...
2.bulk_create()
def ab_res(request):
book_list = []
for i in range(1000):
book_obj = models.MySqlite(name='第%s本' % (i+1))
book_list.append(book_obj)
models.MySqlite.objects.bulk_create(book_list)
obj = models.MySqlite.objects.all()
return render(request, 'ab_res.html', locals())
ajax结合sweetlet二次删除确认
1.在前端书写代码,并且绑定button,可以将关键数据存入到按钮的attr中,方便拿取
传数据的两种方式:
1.通过data在请求体中传入的ID值
2.直接在url使用反向解析拿到传入的ID值
2.将要处理的数据传入后端进行操作,后端返回状态码已经信息
3.前端接受并根据状态码进行回调函数触发提醒框操作
模板使用
<script>
$('.del').on('click',function () {
let currentBtn = $(this);
swal({
title: "你确定要删吗?",
text: "你可要考虑清除哦,可能需要拎包跑路哦!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "是的,老子就要删!",
cancelButtonText: "算了,算了!",
closeOnConfirm:false,
closeOnCancel: false,
showLoaderOnConfirm: true
},
function(isConfirm) {
if (isConfirm) {
$.ajax({
{#url:'/delete/user/' + currentBtn.attr('delete_id'),
url:'/book_list/',
type:'post',
data:{'delete_id':currentBtn.attr('author_id')},
success:function (args) {
console.log(typeof(args))
if(args.code === 1000){
swal("\r\n", args.msg, "success");
{#window.location.reload()#}
currentBtn.parent().parent().remove()
}else{
swal('error!','出现未知错误','error')
}
}
})
} else {
swal("False", "已取消", "error");
}
});
})
</script>
ajax自定义分页器推导
1.后端
author_objs = models.Author.objects.all()
current_page = request.GET.get('page', 1)
count_page = author_objs.count()
div_page, more = divmod(count_page, 10)
if more:
div_page += 1
try:
current_page = int(current_page)
except Exception:
current_page = 1
if current_page > div_page:
current_page = 1
page_number = 10
start_page = (current_page - 1) * page_number
end_page = current_page * page_number
page_html = ''
xxx = current_page
if current_page < 6:
current_page = 6
if current_page >= div_page - 5:
current_page = div_page - 5
for i in range(current_page - 5, current_page + 6):
if i == xxx:
page_html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
else:
page_html += '<li class=""><a href="?page=%s">%s</a></li>' % (i, i)
data_queryset = author_objs[start_page:end_page]
return render(request, 'ab_fy.html', locals())
<body>
{% for data in data_queryset %}
<p>{{ data.name }}</p>
{% endfor %}
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{{ page_html|safe }}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</body>
自定义分页器的使用
自定义工具的使用
当需要使用非django第三方组件以及自己写的第三方代码时
通常会咋子应用下或者django项目下创建一个utils文件夹
并且在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
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):
if self.all_pager <= self.pager_count:
pager_start = 1
pager_end = self.all_pager + 1
else:
if self.current_page <= self.pager_count_half:
pager_start = 1
pager_end = self.pager_count + 1
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 = []
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)
自定义分页器的使用
1.先拿到数据库中数据对象
books_queryset = models.Book.objects.all()
2.通过前端获取当前页
current_page = request.GET.get('page',1)
3.统计数据总数
all_count = book_queryset.count()
4.调用类传入参数
page_obj = pagemaker.Pagination(current_page=current_page, all_count=allcount)
5.调用对象的函数生产start和end参数拿到每页的数据
booK_queryset = book_queryset[page_obj.start:page_obj.end]
6.直接向前端传入对象
return render(request, 'book_list.html', locals())
接收到的数据直接渲染
由于在后端代码中已经将分页器的代码写好所以前端直接调用分页器的
{{page_obj.page_html:safe}}直接进行分页操作