自定义分页器和form组件
作者:互联网
批量操作数据
浏览器访问一个django路由 立刻创建10万条数据并展示到前端页面
create()、all()
涉及到大批量数据的创建 直接使用create可能会造成数据库崩溃
批量数据创建>>>:bulk_create()
批量数据修改>>>:bulk_update()
def index(request):
# for i in range(100000):
# models.Book.objects.create(title=f'第{i}本书')
# book_query = models.Book.objects.all()
book_list = []
for i in range(100000):
book_obj = models.Book(title=f'第{i}本书')
book_list.append(book_obj)
models.Book.objects.bulk_create(book_list) # 批量创建
models.Book.objects.bulk_update() # 批量删除
book_query = models.Book.objects.all()
return render(request,'booList.html',locals())
'''上面的for循环可以用列表生成式写成一行'''
[models.Book(title=f'第{i}本书')for i in range(100000)]
批量数据展示
'''分页器推导流程'''
当数据量比较大的时候 页面展示应该考虑分页
1.QuerySet切片操作
book_query = models.Book.objects.all()[0:10] 切片操作顾头不顾尾
2.分页样式添加
3.页码展示
如何根据总数据和每页展示的数据得出总页码 divmod()
判断divmod的第二个参数是否有值
4.如何渲染出所有的页码标签
前端模板语法不支持range 但是后端支持 我们可以在后端创建好html标签然后传递给html页面使用 |safe
5.如何限制住展示的页面标签个数
页码推荐使用奇数位(对称美) 利用当前页前后固定位数来限制
6.首尾页码展示范围问题
# 代码展示
# 计算总共的数据条数
all_count = book_data.count()
# 2.自定义每页展示的数据条数
per_page_num = 10
all_page_num, more = divmod(all_count, per_page_num)
if more:
all_page_num += 1
# 1.获取前端想要展示的页码
current_page = request.GET.get('page', 1) # 获取用户指定的page 如果没有则默认展示第一页
try:
current_page = int(current_page)
except ValueError:
current_page = 1
# 后端提前生成页码标签
html_page = ''
xxx = current_page
if current_page < 6:
xxx = 6
for i in range(xxx - 5, xxx + 6):
if current_page == i:
html_page += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
else:
html_page += '<li><a href="?page=%s">%s</a></li>' % (i, i)
# 3.定义出切片起始位置
start_num = (current_page - 1) * per_page_num
# 4.定义出切片终止位置
end_num = current_page * per_page_num
book_query = book_data[start_num:end_num] # QuerySet [数据对象 数据对象]
自定义分页器
自定义分页器封装代码
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>
form组件
# 编写用户登录功能并且校验用户信息
def ab_form(request):
datadict = {'username':'','password':''}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'summer':
datadict['username'] = '笨蛋!又记错名字啦!!'
if password == '123':
datadict['password'] = '密码不可以是123啦!'
return render(request,'ab_form.html',locals())
前端代码:
<form action="" method="post">
<p>
username: <input type="text" name="username">
<span style="color: blueviolet">{{ datadict.username }}</span>
</p>
<p>
password: <input type="password" name="password">
<span style="color: brown">{{ datadict.password }}</span>
</p>
<input type="submit" value="提交">
</form>
form组件主要功能
1.数据校验
支持提前设置校验规则 之后自动校验
2.渲染页面
支持直接渲染获取用户数据的各种标签
3.展示信息
针对不同的校验失败展示不同的提示信息
用form组件校验用户信息
1.form类的创建
from django import forms
class MyForm(forms.Form):
name = forms.CharField(max_length=32, min_length=3) # 最长32位 最短3位
age = forms.IntegerField(max_value=150, min_value=0) # 最大年龄150 最小年龄0
email = forms.EmailField() # 邮箱格式必须有@符
# form组件校验方法:
is_valid() 用于判断用户输入的值是否全部符合!如果是TURE 不是FALSE
cleaned_data 用于校验用户的输入的数据哪些是符合的
errors 用于校验用户输入的数据哪些是不符合条件的 还会返回不符合的原因
1.form类中的字段默认都是必须填的,少传的话is_valid()肯定会报错
2.如果多传了一些字段的数据的话不参与校验
渲染标签
# 渲染标签的三种方式
1.第一种方式 封装程度高 扩展性差
{{ form_obj.as_p }}
{{ form_obj.as_table }}
{{ form_obj.as_ul }} 无序列表形式
2.第二种方式
可自定义lable参数 扩展性强 但是获取的字段多的时候不好用
{{ form_obj.name.label }}
{{ form_obj.name }}
{{ form_obj.age.label }}
{{ form_obj.age }}
{{ form_obj.email.label }}
{{ form_obj.email }}
3.第三种方式 兼容性最好
{% for form in form_obj %}
{{ form.label }} {{ form }}
{% endfor %}
'''form渲染只渲染获取用户输入的标签 提交按钮需要自己写'''
展示提示信息
# novalidate 取消前端自动校验
前端代码:
<form action="" method="post" novalidate>
{% for form in form_obj %}
<p>{{ form.label }} {{ form }}</p>
<span style="color: blue"> {{ form.errors }}</span>
{% endfor %}
<input type="submit" value="提交">
</form>
后端代码:
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)
else:
print(form_obj.errors)
return render(request,'func.html',locals())
modelform组件
标签:obj,自定义,form,self,current,组件,pager,page 来源: https://www.cnblogs.com/Hsummer/p/16671179.html