分页器与from组件分析
作者:互联网
分页器与from组件分析
批量操作数据
1.浏览器访问django路由,创建十万条数据存储到sqliet3数据库中并展示到前端页面(额,这个有点看电脑创建的多了,有可能数据库就崩了自己上锁了,看命)
for i in range(100000):
models.Book.objects.create(title=f'第{i}本书')
book_query = models.Book.objects.all()
2.我们使用sqlite3数据库也需要下载配置文件,直接database点击download下载即可,可能会下的有点慢耐心等待即可
3.涉及到大批量数据的创建,直接使用create可能会造成数据库崩溃,所以就需要另辟蹊径
批量数据创建 >>>: bulk_create()
批量数据修改 >>>: bulk_update()
4.实现快速创建十万数据
def index(request):
# for i in range(100000):
# models.Book.objects.create(title=f'第{i}本书')
book_list = []
for i in range(100000):
book_obj = models.Book(title=f'第{i}本书')
book_list.append(book_obj)
# 简写版本(列表生成式):
book_list = [models.Book(title=f'第{i}本书') for i in range(10000)]
models.Book.objects.bulk_create(book_list)
book_query = models.Book.objects.all()
return render(request,'index.html',locals())
分页器推到流程
1.首先我们上面做到了将所有的书全部展示到页面,那么我们就应该将他进行分页处理,方便我们查看
2.使用QuerySet切片操作,然后我们就可以通过浏览器上方浏览到我们所切到的页数
3.优化上一步我们那样做太麻烦了,也不适用于大众所以我们要给它加上一个简易的分页器,所以我们就需要到Bootstrap上寻找一个分页器到html页面
4.然后绑定传输页面所需要的值,但是由于该模板页数过小我们就应该在他的基础上进行修改
5.我们需要使用for循环给它将地址循环出来,但是由于html前端不支持for循环那么我们就需要使用后端循环传给前端进行使用
6.我们就需要将前方的页码数据进行优化,使用divmod判断有多少个分组,如果有剩余那么分组加一
7.将分好组的按钮信息传入前端由前端展示,页码推荐使用奇数位,利用的那个钱页面固定位数来限制
8.但是我们会发现到一后还是会有负位按键,那么我们判断是否为1然后将位数固定在奇数位即可
9.将按钮显示在某页
def index(request):
# for i in range(100000):
# models.Book.objects.create(title=f'第{i}本书')
# book_list = []
# for i in range(100000):
# book_obj = models.Book(title=f'第{i}本书')
# book_list.append(book_obj)
# 简写版本(列表生成式):
# book_list = [models.Book(title=f'第{i}本书') for i in range(10000)]
# models.Book.objects.bulk_create(book_list)
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
current_page = request.GET.get('page', 1)
try:
current_page = int(current_page)
except ValueError:
current_page = 1
html_page = ''
now_page = current_page
if current_page < 6:
now_page = 6
elif current_page >= all_page_num:
now_page = all_page_num-4
for i in range(now_page - 5,now_page + 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)
# print('总页码:',all_page_num)
start_num = (current_page-1) * per_page_num
end_num = current_page * per_page_num
book_query = models.Book.objects.all()[start_num:end_num]
return render(request,'index.html',locals())
分页器模板
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)
自定义分页器
1.我们也可以使用自定义分页器导入即可
2.后端配置
from app01.plugins import mypage
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())
3.前端配置
<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组件校验前戏
1.自己搓一个校验器
def ab_form(request):
data_dict = {'username':'','password':''}
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if username == 'joseph':
data_dict['username'] = 'joseph想去玩'
if password == 520:
data_dict['password'] = '520好想抱抱她'
return render(request,'ab_form.html',locals())
form组件简介
form组件
1.数据校验
支持提前设置各种校验规则,之后自动校验
2.渲染页面
支持直接渲染获取用户数据的各种标签
3.展示信息
支持针对不同的校验失败展示不同的提示
form类型简单创建
from django import forms # 导入forms模块
class MyForm(forms.Form):
name = forms.CharField(max_length=24,min_length=2) # 设置姓名最常为24个字符,最短为2个字符
age = forms.IntegerField(max_value=180,min_value=0) # 设置年龄最大为180岁,最小为0岁
email = forms.EmailField() # 邮箱必须符合邮箱格式(最少要带一个@符)
form组件校验数据
1.传递待校验数据
from app01 import views
form_obj = views.MyForm({'name':'joseph','age': 21, 'email':520})
2.判断所有受是否符合校验
form_obj.is_valid()
False
3.获取符合校验规则的数据
form_obj.cleaned_data
{'name': 'joseph', 'age': 21}
4.获取不符合校验规则的数据以及错误的原因
form_obj.errors
{'email': ['Enter a valid email address.']}
5.正确数据
form_obj = views.MyForm({'name':'joseph','age': 21, 'email':'520@qq.com'})
form_obj.cleaned_data
6.额外数据
form_obj = views.MyForm({'name':'joseph','age': 21, 'email':'520@qq.com','hobby':'read'})
form_obj.cleaned_data
7.特性
form类中编写的字段默认是必填的,少传通不过校验,然而多传则不校验,全程忽略,我只想要我要的其他人都是空气
form组件渲染标签
1.注释分类
{# 第一种注释,在浏览器页面看不到,是html自带的一种注释 #}
<!--第二种注释,在浏览器页面可以看到-->
2.渲染标签功能
方式一:(封装程度高,但是扩展性较差)
{{ form_obj.as_p }}
{{ form_obj.as_table }}
{{ form_obj.as_ul }}
方式二:(封装程度低,扩展性好,但是编写困难,麻烦)
{{ form_obj.name.label }}
{{ form_obj.name }}
{{ form_obj.age.label }}
{{ form_obj.age }}
{{ form_obj.email.label }}
{{ form_obj.email }}
方式三:(推荐使用)
{% for form in form_obj %}
<p>{{ form.label }}{{ form }}</p>
{% endfor %}
form组件展示信息
1.form表单如何取消浏览器自动添加的数据校验功能
<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())
2.修改默认字符格式
LANGUAGE_CODE = 'en-us' # 英文
from django.conf import global_settings # 字符介绍地址
('zh-hans', gettext_noop('Simplified Chinese')), # 简体中文
('zh-hant', gettext_noop('Traditional Chinese')), # 繁体中文
form组件字段常见参数
字段参数 | 功能 |
---|---|
max_length | 最大位数 |
min_length | 最小位数 |
max_value | 最大值 |
min_value | 最小值 |
label | 字段注释 |
error-messages | 错误提示 |
required | 是否为空 |
widget | 标签类型,标签属性 |
initial | 默认值 |
validathors | 正则校验 |
form组件钩子函数
提供自定义的校验方式
局部钩子:校验单个(局部)字段
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组件源码分析
1.is_vaLid
def is_valid(self): # 本身什么功能也没有
"""Return True if the form has no errors, or False otherwise."""
return self.is_bound and not self.errors
2.is_bound
无论怎样都是空
self.is_bound = data is not None or files is not None
3.errors
def errors(self):
"""Return an ErrorDict for the data provided for the form."""
if self._errors is None: # 前面带了下划线就是不想让你访问的,大家都墨守成规
self.full_clean()
return self._errors
4._errors
self._errors = None # Stores the errors after clean() has been called. 仅做展示是个空
5.full_clean
def full_clean(self): # 终于快到了
self._clean_fields()
self._clean_form()
self._post_clean()
6._post_clean
def _post_clean(self): # 空
"""
An internal hook for performing additional cleaning after form cleaning
is complete. Used for model validation in model forms.
"""
pass
7._clean_form
def _clean_form(self):
try:
cleaned_data = self.clean()
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data
8._clean_fields
def _clean_fields(self):
for name, field in self.fields.items():
if field.disabled:
value = self.get_initial_for_field(field, name)
else:
value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
try:
if isinstance(field, FileField):
initial = self.get_initial_for_field(field, name)
value = field.clean(value, initial)
else:
value = field.clean(value)
self.cleaned_data[name] = value
if hasattr(self, 'clean_%s' % name):
value = getattr(self, 'clean_%s' % name)()
self.cleaned_data[name] = value
except ValidationError as e:
self.add_error(name, e)
modelform组件
1.modelform是form的优化版本 使用更简单 功能更强大,底层也是使用面向对象反射与钩子函数
class MyModelForm(forms.ModelForm):
class Meta:
model = models.User
fields = '__all__'
def clean_name(self):
name = self.cleaned_data.get('name')
res = models.User.objects.filter(name=name).first()
if res:
self.add_error('name','用户名已存在')
return name
标签:分析,obj,分页,form,self,current,组件,page,name 来源: https://www.cnblogs.com/joseph-bright/p/16671213.html