Day 11分页器和from组件
一、批量写入数据
方式一
from faker import Faker
from app01 import models
import random
f = Faker(locale='zh/CN')
def index(request):
for i in range(100):
models.User.objects.create(
name=f.name,
age=random.randint(0, 1),
salary=random.randint(8000.15000),
address=f.addres()
)
这样的方法不推荐,相当于启动了100次数据库,对数据库压力比较大
方式二
使用django.db.models.query.QuerySet.==bulk_create()==批量创建对象,减少SQL查询次数。改进如下:
def bulk_create(self, objs, batch_size=None):
objs = list(objs)
objs 为列表格式 batch_size分几次写入,默认一次
def index(request):
user_list = []
for i in range(100):
user = models.User(
name=f.name,
age=random.randint(0, 1),
salary=random.randint(8000.15000),
address=f.addres()
)
user_list.append(user)
models.User.objects.bulk_create(user_list, 10) # 分十次写入
牺牲内存减少数据库压力
二、分页器的使用
1 分页器组件介绍
1 项目数据量大了以后,比如涉及到分页,一页一页的加载显示
2 django中分页器组件,把分页常用的东西,封装到一个类中
3 实例化得到一个对象,对象里有属性和方法
# 实例化得到对象
# 第一个参数:要分页的数据,book_list
# 第二个参数:显示的条数
paginator = Paginator(user_list, 9)
2 Paginator常用属性和方法:
(1)count:总共有多少条数据。
(2)num_pages:总共有多少页
(3)per_page:每页显示的条数
(4)page_range:页面的区间。比如有三页,那么就是range(1,4)。
3 Page常用属性和方法:
(1)has_next:是否还有下一页。
(2)has_previous:是否还有上一页。
(3)next_page_number: 下一页的页码。
(4)previous_page_number:上一页的页码:
(5)number:当前页。
(6)start_index: 当前这一页的第一条数据的索引值。
(7)end_index:当前这一页的最后一条数据的索引值。
分页器使用(带省略号)
视图
def index(request):
current_page = int(request.GET.get('page', 1)) # get请求 如果没有默认取1
# print(request.GET)
# print(current_page)
user_list = models.User.objects.all()
# 实例化得到对象
# 第一个参数:要分页的数据,book_list
# 第二个参数:显示的条数
paginator = Paginator(user_list, 5)
# 页码生成器
page_range = [] # 需要显示的页码数
# 去到某一页的page对象
single_user_list = paginator.page(current_page) # 当前页码数
page_all = paginator.num_pages # 总页码数·
mid_pages = 3 # 中间段显示的页码数
page_goto = 1 # 默认跳转的页码
if page_all <= 2 + mid_pages: # 当页码数量小于6个时候
page_range = paginator.page_range # 全部显示
else:
# 添加应该显示的页码
page_range += [1, page_all] # 列表的扩充
page_range += [current_page - 1, current_page, current_page + 1]
# 当前页是头尾 范围拓展2页
if current_page == 1 or current_page == page_all:
page_range += [current_page - 2, current_page + 2]
# 去掉超出范围的页码
page_range = filter(lambda x: x > 0 and x < page_all + 1, page_range)
# print(page_range)
# 排序去重
page_range = sorted(list(set(page_range)))
print(page_range)
# 查漏补缺
# 从第二个开始遍历,查看页码间隔,若间隔为0则是连续的
# 若间隔为1则不上页码:间隔超过1 补上省略号
t = 1
for i in range(len(page_range) - 1):
step = page_range[t] - page_range[t - 1]
if step >= 2:
if step == 2:
page_range.insert(t, page_range[t] - 1)
else:
page_goto = page_range[t - 1] + 1
page_range.insert(t, '...')
t += 1
t += 1
# 优化结果后的页码列表
paginator.page_range_new = page_range
# 默认跳转页的值
paginator.page_goto = page_goto
paginator.current_page = current_page
return render(request, 'index.html', {
'paginator': paginator,
'user_list': user_list,
'single_user_list': single_user_list,
})
html
<div class="col-md-6 col-md-offset-3">
<table class="table table-striped">
<thead>
<tr>
<th>序号</th>
<th>名字</th>
<th>年龄</th>
<th>薪资</th>
<th>地址</th>
</tr>
</thead>
<tbody>
{% for user in single_user_list %}
<tr>
<th>{{ user.id }}</th>
<th>{{ user.name }}</th>
<th>{{ user.age }}</th>
<th>{{ user.salary }}</th>
<th>{{ user.address }}</th>
</tr>
{% endfor %}
</tbody>
</table>
<nav aria-label="..." class="text-center">
<ul class="pagination pagination-lg">
<li><a href="/?page={% if single_user_list.has_previous %}
{{ single_user_list.previous_page_number }}
{% else %}
{{ single_user_list.number }}
{% endif %} ">上一页</a></li>
{% for page in paginator.page_range_new %}
{% if page == '...' %}
<li><span>...</span></li>
{% elif page == paginator.current_page %}
<li class="active"><a href="/?page={{ page }}">{{ page }}</a></li>
{% else %}
<li><a href="/?page={{ page }}">{{ page }}</a></li>
{% endif %}
{% endfor %}
<li><a href="/?page={% if single_user_list.has_next %}
{{ single_user_list.next_page_number }}
{% else %}
{{ single_user_list.number }}
{% endif %} ">下一页</a></li>
</ul>
</nav>
<span>共{{ user_list.count }}篇博文。
当前第{{ paginator.current_page }}页,
共{{ paginator.num_pages }}页</span>
</div>
最终的实现效果
三、forms组件介绍
1 注册功能,登录功能,前端需要校验(字段长度,邮箱是否合法。。。)
2 前端校验可以没有,后端校验是必须的,使用传统方式 if判断写的很多
3 借助于forms组件,可以快速实现字段的校验
from django.forms import Form
四、forms校验字段功能
1.在app01下创建一个py文件
2.导入组件
from django import forms
3.定义组件功能
class CheckUser(forms.Form):
name = forms.CharField(required=True, # 是否需要该字段默认为True
max_length=32, # 最大长度
min_length=4, # 最小长度
label='用户名') # 此字段的详细名称,用于在表单中显示此#字段。
# 默认情况下,如果Field是#Form的一部分,则Django将使用表单域名称的“漂亮”版本。
password = forms.CharField(required=True,
max_length=18,
min_length=6,
label='密码')
age = forms.IntegerField(max_value=100,
min_value=0,
label='年龄')
4.在视图函数中调用
from app01 import myfrom
def Up_In(request):
if request.method == 'POST':
data = request.POST
print(data)
form = myfrom.CheckUser(data=data) # 传入参数
if form.is_valid(): # 表单匹配正确 可以使用
print('校验通过')
else:
print(form.cleaned_data) # 校验通过的字段
print('校验失败')
# 哪个字段失败了?失败的原因是什么
print(form.errors)
print(type(form.errors))
#### 重写了__str__
print(form.errors.as_json())
print(form.errors.as_data())
return render(request, 'Up_In.html')
五、forms渲染模板功能
视图
def automatic_form(request):
form = myfrom.CheckUser()
return render(request, 'demo.html', {'form': form})
模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>半自动渲染模板1</h1>
<form action="" method="post">
<p>用户名:{{ form.name }}</p>
<p>邮箱:{{ form.password }}</p>
<p>年龄:{{ form.age }}</p>
<p><input type="submit" value="提交"></p>
</form>
<h1>半自动渲染模板2</h1>
<form action="" method="post">
<p>{{ form.name.label }}{{ form.name }}</p>
<p>{{ form.password.label }}{{ form.password }}</p>
<p>{{ form.age.label }}{{ form.age }}</p>
<p><input type="submit" value="提交"></p>
</form>
<h1>半自动渲染模板3</h1>
<form action="" method="post">
{% for foo in form %}
<p>{{ foo.label }}{{ foo }}</p>
{% endfor %}
<p><input type="submit" value="提交"></p>
</form>
<h1>全自动渲染模板</h1>
<form action="" method="post">
{{ form.as_p }}
<p><input type="submit" value="提交"></p>
</form>
</body>
</html>