一、Ajax简介
异步提交,局部刷新
AJAX 不是新的编程语言,而是一种使用现有标准的新方法
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
二、Ajax基本语法
1.index.html
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p>
<button id="btn">点我</button>
</p>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
// 先给按钮绑定一个点击事件
$('#btn').click(function () {
// 朝后端发送ajax请求
$.ajax({
// 1.指定朝哪个后端发送ajax请求
url: '', // 不写就是朝当前地址提交
// 2.请求方式
type: 'post', // 不指定默认就是get 都是小写
// 3.数据
data: {'i1': $('#d1').val(), 'i2': $('#d2').val()},
// 4.回调函数:当后端给你返回结果的时候会自动触发 args接收后端返回结果
success: function (args) {
{#alert(args)#}
$('#d3').val(args)
}
})
})
</script>
2.views.py
from django.shortcuts import render, HttpResponse
def ab_ajax(request):
if request.method == "POST":
# print(request.POST)
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
# 先转成整形再加
i3 = int(i1) + int(i2)
print(i3)
return HttpResponse(i3)
return render(request, 'index.html')
3.urls.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('ab_ajax/', views.ab_ajax),
# ajax发送json格式数据
path('ab_json/', views.ab_json),
# ajax发送文件
path('ab_file/', views.ab_file),
# 序列化组件相关
path('ab_ser/', views.ab_ser),
# 批量插入数据
path('ab_pl/', views.ab_pl),
]
二、Ajax发送数据
1.Ajax发送json格式数据
1.1.ab_json.html
<button class="btn btn-danger" id="d1">点我</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$('#d1').click(function () {
$.ajax({
url: '',
type: 'post',
data: JSON.stringify({'username': 'qiansuiyou', 'age': 100}), // {"username":"qiansuiyou","age":100}
contentType: 'application/json', // 指定编码格式
success: function (args) {
}
})
})
</script>
1.2.views.py
def ab_json(request):
json_bytes = request.body
print(json_bytes, type(json_bytes)) # b'{"username":"qiansuiyou","age":100}' <class 'bytes'>
return render(request, 'ab_json.html')
2.Ajax发送文件数据
2.1.ab_file.html
<p>username:<input type="text" id="d1"></p>
<p>password:<input type="text" id="d2"></p>
<p><input type="file" id="d3"></p>
<button id="d4">点我</button>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
// 点击按钮朝后端发送普通键值对和文件数据
$('#d4').on('click', function () {
// 1.需要先利用FormData内置对象
let formDateObj = new FormData();
// 2.先添加普通的键值对
formDateObj.append('username', $('#d1').val());
formDateObj.append('password', $('#d2').val());
// 3.添加文件对象
formDateObj.append('myfile', $('#d3')[0].files[0]);
// 4.将对象基于Ajax发送给后端
$.ajax({
url: '',
type: 'post',
data: formDateObj, // 直接将对象放入data后面即可
//Ajax发送文件必须要指定的两个参数
contentType: false, // 不需要使用任何编码 django后端能够自动识别formdata对象
processData: false, // 告诉你的浏览器不要对你的数据进行任何处理
success: function () {
}
})
})
</script>
2.2views.py
def ab_file(request):
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return render(request, 'ab_file.html')
三、django自带的序列号组件
1.models.py
class User(models.Model):
username = models.CharField(max_length=32, verbose_name='姓名')
age = models.IntegerField(verbose_name='年龄')
gender_choices = (
(1, 'male'),
(2, 'female'),
(3, 'others')
)
gender = models.IntegerField(choices=gender_choices, verbose_name='性别')
class Book(models.Model):
title = models.CharField(max_length=32)
2.views.py
from django.shortcuts import render, HttpResponse
from app01 import models
from django.http import JsonResponse
from django.core import serializers
def ab_ser(request):
user_queryset = models.User.objects.all()
# user_list = []
# for user_obj in user_queryset:
# tmp = {
# 'pk': user_obj.pk,
# 'username': user_obj.username,
# 'age': user_obj.age,
# 'gender': user_obj.get_gender_display()
# }
# user_list.append(tmp)
# return JsonResponse(user_list, safe=False)
# 序列化模块
res = serializers.serialize('json', user_queryset)
return HttpResponse(res)
四、批量插入数据
1.ab_pl.html
{% for book_obj in book_queryset %}
<p>{{ book_obj.title }}</p>
{% endfor %}
2.views.py
def ab_pl(request):
# 先给Book插入1000条数据
# for i in range(1000):
# models.Book.objects.create(title=f'第{i}本书')
# 在将所有的数据查询并展示到前端页面
# book_queryset = models.Book.objects.all()
# 批量插入
book_list = []
for i in range(1000):
book_obj = models.Book(title=f'第{i}本书')
book_list.append(book_obj)
models.Book.objects.bulk_create(book_list)
book_queryset = models.Book.objects.all()
"""当你想要批量插入数据的时候使用orm给你提供的bulk_create能够大大的减少操作时间"""
return render(request, 'ab_pl.html', locals())
五、自定义分页器
当需要使用到非django内置的第三方功能或者组件代码的时候
一般情况下会创建一个名为utils文件夹,在该文件夹内对模块进行功能性划分
自定义分页器是基于bootstrap3样式来的,所有需要提前导入bootstrap3
1.utils/mypage.py
class Pagination(object):
def __init__(self, current_page, all_count, per_page_num=10, 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)
2.views.py
from utils.mypage import Pagination
def ab_pl(request):
# 分页
book_queryset = models.Book.objects.all()
current_page = request.GET.get('page', 1)
all_count = book_queryset.count()
# 1.传值生成对象
page_obj = Pagination(current_page=current_page, all_count=all_count)
# 2.直接对总数据进行切片操作
page_queryset = book_queryset[page_obj.start:page_obj.end]
return render(request, 'ab_pl.html', locals())
3.ap_pl.html
{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}