其他分享
首页 > 其他分享> > 分页器与from组件分析

分页器与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