Ajax简介,批量操作数据,自定义分页器,form组件,钩子函数
作者:互联网
- Ajax简介
- 批量操作数据
- 自定义分页器
- form组件
- 钩子函数
Ajax简介
同步
提交完任务之后原地等待任务的结果 期间不做任何事
异步
提交完任务之后不原地等待直接去做其他事 结果自动提醒
1. ajax是异步提交,局部刷新
2. ajax是js自带的功能,不是一门新的技术,我们学习的是jQuery封装之后的版本,所以你在使用ajax之前要将jQuery导进来
ajax基本语法
$.ajax({
url:'', 控制数据提交的默认地址
type:'', 控制请求方式,默认是get请求
data:{}, 组织提交的数据
success:function(args){
异步回调函数
}
})
后端返回来的所有的值都会被这个ages形参接收
ajax数据编码格式
Content-Type
格式1:urlencoded
数据格式: name=jason&pwd=123&hobby=read
django后端统一处理到request.POST中
格式2:formdata
数据格式: 无法查阅
django后端自动将文件数据处理到request.FILES 普通数据request.POST
格式3:application/json
数据格式: json格式
django后端不会处理 在request.body中存储(bytes类型) 自己处理
语法注意事项
data: JSON.stringify({'name':'jason','pwd':123}),
contentType:'application/json',
前端中传数据你必须加上这两条
在后端中你要从request.body
中拿数据,此时拿到的是bytes类型,我们需要通过json.loads
转为json格式
ajax携带文件数据
$('#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) {
}
})
})
回调函数参数问题
我们在用ajax的回调函数success的时候,后端传回来的数据都会被success的形参所接收,通常情况下都是返回json格式数据。
但是ajax是局部刷新的,我们不能让它返回一个页面你说是不
HttpResponse和JsonResponse返回值到前端的区别
HttpResponse返回给前端的都是一些字符串类型的,我们需要用 JSON.parse
将他转为对象才能用点的方式取值
JsonResponse返回给前端会自动转换为对象。
前端针对HttpResponse和JsonResponse返回的json格式数据处理策略不同
前者不会自动反序列化 而后者会自动反序列化
如果想让前者也自动反序列化可以添加一个固定的参数
dataType:'JSON'
stringify与parse方法
1. JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
2. JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串
django序列化模块
def ser(request):
#拿到用户表里面的所有的用户对象
user_list=models.User.objects.all()
#导入内置序列化模块
from django.core import serializers
#调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
ret=serializers.serialize('json',user_list)
return HttpResponse(ret)
批量操作数据
浏览器访问一个django路由 立刻创建10万条数据并展示到前端页面
def index(request):
# for i in range(1000):
# models.Book.objects.create(title=f'第{i}本书')
book_query = models.Book.objects.all()
return render(request,'book.html',locals())
但是这样数据过于庞大,导致服务器崩溃,可以使用下面的方法
让循环在内存中实现,我们直接拿数据
def index(request):
book_list = []
for i in range(10000):
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,'book.html',locals())
1. 批量数据创建>>>:models.Book.object.bulk_create()
2. 批量数据修改>>>:models.Book.object.bulk_update()
批量数据展示
当数据量很大很大很大的时候我们就要考虑分页
1. QuerySet切片操作
book_query = models.Book.objects.all()[start_page_num,end_page_num]
2. 分页样式添加
自己取bootstrap上找一个
3. 页码展示
divmod()
divmod(100,10) >>> (10,0)
divmod(99,10)>>> (9,9)
divmod(101,10)>>> (10,1)
哇塞,这样我们就可以用解压赋值,然后拿到前面的数字设置我们需要多少页了
4. 如何渲染出所有的页码标签
我们不免想到在前端用for循环,但是会发现前端并不支持,但是后端支持啊,所以我们可以在后端进行for循环,然后将循环后的值返回给前端就大功告成了
5. 但是告诉你个秘密,我有模板你气不气
look!!
前端:
<body>
<div class="container">
<div class="row">
<div class='col-md-8 col-md-offset-2 text-center'>
{% for book_obj in page_query %}
<p class="text-center">{{ book_obj.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
</div>
</div>
</div>
后端:
你要先搞一个plugins第三方模块的文件夹放在app文件夹下,然后建一个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)
views文件中的内容
from django.shortcuts import render
from app01 import models
# Create your views here.
def index(request):
# for i in range(1000):
# models.Book.objects.create(title=f'第{i}本书')
# book_list = []
# for i in range(10000):
# 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_data = models.Book.objects.all()
# # 计算总共多少条数据
# all_count = book_data.count()
# # 自定义每页展示的条数
# per_page_num = 10
# all_page_num,more = divmod(all_count,per_page_num)
# if more:
# all_page_num += 1
# # print('总页码',all_page_num)
# # 1. 获取前端想要展示的数据条数
# current_page = request.GET.get('page', 1)
# try:
# current_page = int(current_page)
# except ValueError:
# current_page = 1
# # 后端for循环
# html_page = ''
# xxx=current_page
# if current_page <6:
# xxx = 6
# for i in range(xxx-5, xxx+6):
# html_page+='<li class="primary"><a href="?page=%s">%s</a></li>'%(i,i)
#
#
#
# # 4. 获取每页展示的条数
# # per_page_num = 10
# # 3. 获取完成切片的最后一页
# end_page_num = current_page * per_page_num
# # 2. 获取切片的起始位置
# start_page_num = (current_page - 1) * per_page_num
#
# book_query = models.Book.objects.all()[start_page_num:end_page_num]
from app01.plugins import mypage
book_query = models.Book.objects.all()
page_obj = mypage.Pagination(current_page=request.GET.get('page'),
all_count=book_query.count()
)
page_query = book_query[page_obj.start:page_obj.end]
return render(request,'book.html',locals())
form组件
form组件有三个功能
1. 数据校验功能
支持提前设置各种校验规则 之后自动校验
2. 页面渲染功能
支持直接渲染获取用户数据的各种标签
3. 展示信息功能
支持针对不同的校验失败展示不同的提示
下面我们一起来看看
首先你要想用form组件就要导form模块,然后在models中创建表,再在views中将表中的信息进行规定
数据校验
传递待校验的数据,在pycharm的虚拟环境中测试
cleaned_data
errors
注意:
在form中出现的字段你都必须要填上,不然会报错
但是如果多传,form不会报错
小知识:
渲染标签功能
方式一(封装程度高 扩展性差)
第二种(封装程度低 扩展性好 编写困难)
字段多的话很麻烦
第三种(推荐使用)
非常好用
注意:
类中以外的所有标签都不会自动渲染 需要自己编写
展示提示信息
form表单如何取消浏览器自动添加的数据校验功能
<form action="" method="post" novalidate> # novalidate 让前端浏览器不作任何校验
<form action="" method="post" novalidate>
{% for form in form_obj %}
<p>
{{ form.label }}{{ form }}
<span style="color: red;">{{ form.errors.0 }}</span>
</p>
{% endfor %}
<input type="submit" value="提交">
def func(request):
form_obj = MyForm()
if request.method == 'POST':
form_obj = MyForm(request.POST)
if form_obj.is_valid():
print(form_obj.cleaned_data)
return render(request,'func.html',locals())
重要的字段参数
max_length、min_length
max_value、min_value
label 字段注释
error_messages 错误提示
required 是否为空
widget 标签类型、标签属性
initial 默认值
validators 正则校验
在下面的模块中我们可以改提示信息的语言
from django.conf import global_settings
钩子函数
提供自定义的校验方式
局部钩子:
校验单个字段
def clean_name(self):
name = self.cleaned_data.get('name')
res = models.User.objects.filter(name=name).first()
if res:
return self.add_error('name','用户名已存在')
return name
全局钩子
校验多个字段
def clean(self):
pwd = self.cleaned_data.get('pwd')
confirm_pwd = self.cleaned_data.get('confirm_pwd')
if not pwd == confirm_pwd:
return self.add_error('confirm_pwd','两次密码不一致')
return self.cleaned_data
标签:自定义,form,models,self,current,Ajax,book,pager,page 来源: https://www.cnblogs.com/scx-xiaochun/p/16671185.html