zoukankan      html  css  js  c++  java
  • Django—分页器与form组件

    分页器

    现成分页器代码

    只需要会使用即可。

    在Django项目下新建utils文件夹,新建一个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:  最多显示的页码个数
    
            用法:
            queryset = model.objects.all()
            page_obj = Pagination(current_page,all_count)
            page_data = queryset[page_obj.start:page_obj.end]
            获取数据用page_data而不再使用原始的queryset
            获取前端分页样式用page_obj.page_html
            """
            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)
    

    如何使用

    后端

    class Books(View):
        def get(self, request):
            book_queryset = models.Book.objects.all()  # 获取所有书籍对象
            current_page = request.GET.get('page', 1)  # 获得当前页码,如果没有就为1
            book_count = book_queryset.count()  # 获取数据总条数
    
            # 1 分页器类实例化出对象
            page_obj = Pagination(per_page_num=12, current_page=current_page, all_count=book_count)
            # 2 对数据进行切片操作,每页展示
            page_queryset = book_queryset[page_obj.start:page_obj.end]
    
            return render(request, 'Books.html', locals())
    
    

    前端

    {% for foo in page_queryset %}
    <p>{{ foo.title }}</p>
    {% endfor %}
    
    {{ page_obj.page_html|safe }}
    

    form组件

    form 校验组件

    校验数据通常是前后端都校验,但是前端校验可有可无,后端必须校验

    注册功能需求:
    用户输入的用户名种不能包含‘虫合’,不可小于三位,不可大于八位
    	如果包含了,就提示用户---》太暴力了
    用户输入的密码,不可小于三位,不可大于八位
    	太短太长都提示
        
        
    搭建步骤:
        1.搭建前端页面                                  >>>                渲染页面
        2.获取前端用户提交的数据校验                       >>>                校验数据
        3.对数据的校验的结果 展示到前端页面给用户查看         >>>            展示错误信息
        
     form组件能够自动帮你完成上面的三件事
    

    使用校验组件与钩子函数

    # 1 自己先写一个类
    # 像创建表一样规定了各个输入框需要遵守的规则,以及违反对应规则会抛出的错误
    class Myform(forms.Form):
        username = forms.CharField(max_length=8, min_length=3, error_messages={
            'min_length': '你太短了',
            'max_length': '你太长了',
            'required': '不可为空'
        }, initial='我是初始值', widget= widgets.TextInput(attrs={'class':'form-control others'})#为这个input标签添加了一个类,用attr={}的方式设置                        
         	#widget可以改变input框的type属性值
                                   
        pwd = forms.CharField(max_length=8, min_length=3, error_messages={
            'min_length': '你太短了',
            'max_length': '你太长了',
            'required': '不可为空'
        }, initial='我是初始值',widget=widgets.PasswordInput())
    
        
    #2 后端代码
    def reg(request):
        form_obj = Myform()#将自己写的类实例化出一个对象,若请求方式为get则不通过校验,直接将form_obj传到前端页面,提供渲染页面的功能
        
        if request.method=='POST':
            #由于request.POST本身就是个大字典,直接扔进去做校验
            form_obj=Myform(request.POST) 
            
            if form_obj.is_valid():
                #is_valid判断是否所有键值对都满足规则,只有都满足时is_valid才为真
                return HttpResponse('合法')
    		
        return render(request,'reg.html',locals())
    
    #3 前端代码
    <form action="" method="post" novalidate> 
    #novalidate是告诉浏览器无需在浏览器做校验
    
    {% for foo in form_obj %}
        <p>{{ foo.label }}: {{ foo }}</p>
        <span style="color: red">{{ foo.errors.0 }}</span>
        #foo.errors拿到的是列表的错误信息,取第一个直接拿出错误信息,如没有错误则为空
    {% endfor %}
    <input type="submit">
    
    
    #局部钩子 校验用户输入的用户名种不得包含‘虫合’(写在自定的Myform类中)
        def clean_username(self):
            username = self.cleaned_data.get('username')
    		#cleaned_data是一个字典,如果键值对经过之前的校验并通过了,就会放在这里面
    		#与cleaned_data相反的是errors,也是字典,保存的是校验不通过的字段以及原因
            if '虫合' in username:
                # 给username字段下面提示错误信息
                self.add_error('username', '太暴力了')
            return self.cleaned_data
    		#return username
    		
        
    #全局钩子 校验用户名与密码不得相同
        def clean(self):
            username=self.cleaned_data.get('username')
            pwd=self.cleaned_data.get('pwd')
            if pwd==username:
                self.add_error('pwd','密码不得与用户名相同')
            return self.cleaned_data
            #return pwd
    
    

    三种渲染方式

    如何渲染页面
        1.forms组件只会帮你渲染获取用户输入(输入,选择,下拉框...)的标签  提交按钮需要你自己手动写
        
        <p>三种渲染前端页面的方式</p>
        <p>第一种渲染前端页面的方式:封装程度太高了 标签样式及参数不方便调整 可扩展性差(不推荐使用)
        {{ form_obj.as_p }}
        {{ form_obj.as_ul }}
        </p>
    
        <p>第二种渲染页面的方式:扩展性较高 不足之处在于 需要你手写的代码量比较多(不推荐使用)</p>
        <p>
            {{ form_obj.username.label }}{{ form_obj.username }}
        </p>
        <p>
            {{ form_obj.password.label }}{{ form_obj.password }}
        </p>
        <p>
            {{ form_obj.email.label }}{{ form_obj.email }}
        </p>
    
        <p>第三种渲染前端页面的方式:代码量和扩展性都很高(推荐使用)</p>
        {% for foo in form_obj %}
        <p>{{ foo.label }}{{ foo }}</p>
        {% endfor %}
    

    正则校验*

    每个字段 还支持正则校验
        from django import forms
        from django.forms import Form
        from django.core.validators import RegexValidator
        
        
        
    class MyForm(Form):
        user = forms.CharField(
            validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
        )
  • 相关阅读:
    Elasticsearch拼音分词和IK分词的安装及使用
    Java同步、异步区别
    Elasticsearch深入搜索之全文搜索及JavaAPI使用
    Elasticsearch学习笔记
    Elasticsearch拼音和ik分词器的结合应用
    Elasticsearch深入搜索之结构化搜索及JavaAPI的使用
    Java反射的理解
    打印三个长宽不同的矩形
    是非人生 — 一个菜鸟程序员的5年职场路 第23节
    是非人生 — 一个菜鸟程序员的5年职场路 第35节
  • 原文地址:https://www.cnblogs.com/Sheppard/p/11761298.html
Copyright © 2011-2022 走看看