Ajax基本操作
# 基于上面的图书管理系统环境继续学习
'''特点:异步提交,局部刷新'''
Ajax是js自带的功能,不是一门新的技术点,我们学习的是jQuery封装之后的版本
1.基础语法
$.ajax({
url:'', 控制数据的提交地址,等价于form表单的action参数
type:'', 控制请求方式(默认get请求,小写)
data:{}, 组织提交的数据
success:function(形参){
异步回调函数
}
})
案例:
1.在app01的urls.py中添加路由
path('abAjax/', views.ab_ajax)
2.在app01的views.py中添加
def ab_ajax(request):
return render(request, 'abAjax.html')
3.在templates中创建abAjax.html,在body中添加
<form action="" method="post">
<input type="text">+<input type="text">=<input type="text">
<input type="submit" value="计算">
</form>
4.启动Django,浏览器输入 127.0.0.1:8000/bms/abAjax
输入值,并点击计算,发现整个页面都会刷新,刷新之后是新页面,之前输入的数据页没了
解决:
1.abAjax.html,修改body
<input type="text" id="d1">+<input type="text" id="d2">=<input type="text" id="d3">
<input type="submit" value="计算" id="subBtn">
<script>
$('#subBtn').click(function () {
// 朝后端发送数据,使用Ajax
$.ajax({
url: '', //等价于form表单的action参数
type: 'post', //等价于form表单的method参数
data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},//要发送给后端的数据
success: function (args) { // 形参args就是用于接收后端返回的数据
//后端接收到了请求,并且给出了一定的反馈
$('#d3').val(args)
}
})
})
$('#d2').blur(function () { // 给d2输入框设置失去焦段的操作
$.ajax({
url: '', //等价于form表单的action参数
type: 'post', //等价于form表单的method参数
data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},//要发送给后端的数据
success: function (args) { // 形参args就是用于接收后端返回的数据
//后端接收到了请求,并且给出了一定的反馈
$('#d3').val(args)
}
})
})
</script>
2.修改views.py的ab_ajax
def ab_ajax(request):
if request.method == 'POST':
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
res = int(i1) + int(i2)
return HttpResponse(res)
return render(request, 'abAjax.html')
3.启动Django,浏览器输入 127.0.0.1:8000/bms/abAjax
输入值,点击计算之后,页面是局部刷新,并且第三个框显示计算结果;或者输入值之后,当第二个框失去焦点(鼠标随便点击其他地方),计算结果也能自动显示
数据编码格式
案例:
打开谷歌浏览器的F12,再次输入值,点击计算,在network这一栏
Resquest Headers中
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Type
'''格式1:urlencoded(Ajax默认的编码格式,form表单和Ajax都能实现)'''
数据格式: name=jason&pwd=123&hobby=read
Django后端统一处理到request.POST中
'''格式2:formdata(form表单和Ajax都能实现)'''
数据格式:无法查阅,二进制
Django后端自动将文件数据处理到request.FILES,普通数据处理到request.POST中
'''格式3:application/json(form表单发不了,只有Ajax可以)'''
数据格式:json格式
Django后端不会处理,在request.body中存储(bytes类型),需要自己处理
'''语法注意事项'''html页面使用Ajax的时候,json格式要改成下面2个
data: JSON.stringify({'name': 'jason', 'pwd': 123}),
contentType: 'application/json',
格式3:json的案例
1.abAjax.html,修改body
<button id="d1">点我</button>
<script>
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
data: JSON.stringify({'name': 'jason', 'pwd': 123}),
contentType: 'application/json',
success:function (args){
}
})
})
</script>
2.修改views.py的ab_ajax
def ab_ajax(request):
if request.is_ajax():
if request.method == 'POST':
print(request.body) # b'{"name":"jason","pwd":123}'
json_bytes = request.body
import json
json_dict = json.loads(json_bytes)
print(json_dict, type(json_dict)) # {'name': 'jason', 'pwd': 123} <class 'dict'>
return render(request, 'abAjax.html')
3.启动Django,浏览器输入 127.0.0.1:8000/bms/abAjax 点击'点我'按钮
浏览器上看到的格式是Content-Type: application/json
pycharm上的打印的是步骤2里的注释内容
ajax携带文件数据
1.abAjax.html,修改body
<input type="text" id="d1">
<input type="file" id="d2">
<button id="d3">点我</button>
<script>
$('#d3').click(function () {
// 1.产生内置对象
let formData = new FormData();
// 2.添加普通数据
formData.append('username', $('#d1').val())
// 3.添加文件数据
formData.append('file', $('#d2')[0].files[0])
// 4.发送Ajax请求
$.ajax({
url: '',
type: 'post',
data: formData,
contentType: false,//不使用任何编码
processData: false,//不处理数据对象
success: function (args) {
}
})
})
</script>
2.修改views.py的ab_ajax
def ab_ajax(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST) # <QueryDict: {'username': ['jason']}>
print(request.FILES) # <MultiValueDict: {'file': [<InMemoryUploadedFile: text.txt (text/plain)>]}>
return render(request, 'abAjax.html')
3.启动Django,浏览器输入 127.0.0.1:8000/bms/abAjax 输入jason,选择text.txt文件,再点击'点我'按钮
pycharm上的打印的是步骤2里的注释内容
回调函数
"""后端跟Ajax交互,不应该再返回页面,通常情况下都是返回json格式数据"""
'''前端针对HttpResponse和JsonResponse返回的json格式数据处理策略不同'''
前者不会自动反序列化,后者会自动反序列化
如果想让前者也自动反序列化,可以在Ajax添加一个固定的参数dataType:'JSON',
# 使用了Ajax之后,后端返回的数据由Ajax回调函数里代码决定,
案例:
1.abAjax.html,修改body
success: function (args) {
alert(args)
window.location.href = args # 使用BOM实现跳转页面
}
2.修改views.py的ab_ajax,添加个return返回值
def ab_ajax(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return HttpResponse('https://www.baidu.com/') # 此处用redirect没用,由Ajax的回调函数决定
return render(request, 'abAjax.html')
# 后端返回了json格式之后,前端需要收到的是string格式,我们需要转成json格式
'''第一种方案,后端使用json模块,前端转换json格式'''
案例:
1.abAjax.html,修改body
success: function (args) {
console.log(typeof args) //string
console.log(args) //{"name": "jason", "pwd": 123} 只是字符串格式
let MyBaby = JSON.parse(args)
console.log(typeof MyBaby) // object
console.log(MyBaby) //{name: 'jason', pwd: 123} json格式
console.log(MyBaby.name) //jason
2.修改views.py的ab_ajax,修改return返回值,需要先导入impor json
return HttpResponse(json.dumps({'name': 'jason', 'pwd': 123}))
'''第二种方案,后端使用JsonResponse,前端直接使用'''
案例:
1.abAjax.html,修改body
success: function (args) {
console.log(typeof args) // object
console.log(args) //{name: 'jason', pwd: 123} json格式
2.修改views.py的ab_ajax,修改return返回值,需要先from django.http import JsonResponse
return JsonResponse({'name': 'jason', 'pwd': 123})
'''第三中方案,后端使用json模块,前端使用dataType参数'''
1.abAjax.html,修改body
dataType:'JSON',
success: function (args) {
console.log(typeof args) // object
console.log(args) //{name: 'jason', pwd: 123} json格式
2.修改views.py的ab_ajax,修改return返回值,需要先导入impor json
return HttpResponse(json.dumps({'name': 'jason', 'pwd': 123}))
sweetaliter介绍
# 关于前端 二次确认框的样式
官网 https://sweetalert.js.org/guides/
使用CDN <script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
在html的script里参考官网的说明
修改图书管理系统的删除二次确认弹窗案例
1.修改booklist.html
<a href="#" class="btn btn-danger btn-xs delBtn">删除</a>
...
{% block js %}
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>
<script>
$('.delBtn').click(function () {
swal({
title: "你真的要删除吗",
text: "如果真的要删了,你要G",
icon: "warning",
buttons: ["取消", "确认"],
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
swal("6!你把书删了", {
icon: "success",
});
} else {
swal("还好你没删");
}
});
})
</script>
{% endblock %}
序列化组件
# 基于上面的图书管理系统环境继续学习
需求:返回json格式的书籍信息
案例:
1.修改app01的urs.py
# 接口url
path('getBook', views.get_book),
2.修改views.py
def get_book(request):
book_query = models.Book.objects.all()
# 将数据全部构造成json格式{'pk':1,'title':'书'}
from django.core import serializers
res = serializers.serialize('json', book_query)
return HttpResponse(res)
3.浏览器访问 127.0.0.1:8000/bms/getBook
批量操作数据
# 创建新Django项目,项目名day62,应用名app01
需求:浏览器访问一个Django路由,立刻创建10万条数据并展示到前端页面
涉及到大批量数据的创建,直接使用create可能会造成数据库崩溃
批量数据创建>>>:bulk_create()
案例:
1.models.py中创建数据库
class Book(models.Model):
title = models.CharField(max_length=32, verbose_name='书名')
2.执行数据库迁移
makemigrations和migrate
3.urs.py中添加路由
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
# 批量数据操作
path('index/',views.index),
]
4.views.py中添加
def index(request):
book_list = []
for i in range(100000):
book_obj = models.Book(title=f'第{i}本书')
book_list.append(book_obj)
# 也可以用列表生成式
# [models.Book(title=f'第{i}本书') for i in range(10000)]
models.Book.objects.bulk_create(book_list) # 批量创建数据
# models.Book.objects.bulk_update() # 批量修改数据
book_query = models.Book.objects.all()
return render(request, 'booklist.html', locals())
5.templates创建booklist.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'jquery.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{% for book_obj in book_query %}
<p>{{ book_obj.title }}</p>
{% endfor %}
</div>
</div>
</div>
</body>
</html>
6.浏览器访问 127.0.0.1:8000/index
自定义分页器
1.在app01目录下创建utils或者plugins 该目录一般放置第三方插件
2.在该目录下创建mypage.py
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)
3.修改settings.py
在最后一行添加
# 每页展示多少条数据
PER_PAGE_NUM = 10
4.修改views.py
def index(request):
from app01.utils import mypage
current_page = request.GET.get('page', 1)
book_query = models.Book.objects.all() # 支持切片
from django.conf import settings
per_page_num = settings.PER_PAGE_NUM
page_obj = mypage.Pagination(
current_page=current_page,
all_count=book_query.count(),
per_page_num=per_page_num,
pager_count=11)
page_query = book_query[page_obj.start:page_obj.end]
return render(request, 'booklist.html', locals())
5.修改templates的booklist.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
<script src="{% static 'jquery.js' %}"></script>
<link rel="stylesheet" href="{% static 'bootstrap-3.4.1-dist/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap-3.4.1-dist/js/bootstrap.min.js' %}"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
{% for book_obj in page_query %}
<p class="text-center">{{ book_obj.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</div>
</div>
</div>
</body>
</html>
6.启动Django,浏览器访问http://127.0.0.1:8000/index
标签:day07,self,request,json,html,pager,page
From: https://www.cnblogs.com/ycmyay/p/17383811.html