• Xadmin控件的实现:〇四查询视图二——分页效果的实现


    在前面的一章里我们实现了如何在一个页面里按照表格的方式显示出来所需要的数据,但是随着数据量的增加,需要做一个分页的效果。

    添加模拟数据

     为了能更好的实现分页的效果,我们用下面的代码生成500条新的数据

    def test(request):
        for i in range(0,500):
            pub = models.Publisher.objects.get(id = (i%2+1))
            book = models.Books(title = str(i),price = i,publisher=pub)
            book.save()
        return HttpResponse('OK')

    创建数据以后,我们在访问Books这个表

    是个超级长的页面,明显不符合我们平时的使用需求。这时候就需要我们这一章讲的分页了

    基础版本分页功能

    以前写了个博客,就讲了如何实现分页,可以点击查看

    基础版的分页代码

    我们可以把前面的那个分页的代码直接贴过来,导入以后看看怎么修改

    修改后的分页代码如下

    from django.utils.safestring import mark_safe
    class Page_Cut():
        def __init__(self,page,url_prefix,data_totle,data_per_page=10,page_show_num=11):
            """
            :param: page:当前页码
            :url_prefix:url前缀
            :data_totle:总数据量
            :date_per_page:每页显示数据条数,默认值为10
            :page_show_num:显示的分页数量,默认值为11
            """
            self.url_prefix = url_prefix  #url前缀
            page_totle,m = divmod(data_totle,data_per_page)
            page_totle = page_totle if not m else page_totle +1    #计算总页码数
            self.page_totle = page_totle
    
            self.page_show_num = page_show_num if page_show_num < self.page_totle else self.page_totle  #显示最大页码数
    
            self.data_per_page = data_per_page
    
            page = 1 if page<1 else page
            page = page_totle if page>page_totle else page
    
            self.page = page
    
            
    
            if page_totle < page_show_num:
                page_show_num = page_totle
    
            page_half = page_show_num // 2                #中间页码数
    
            page_start = page - page_half
            page_end = page + page_half 
    
            if page_start <= 1:
                page_start = 1
                page_end = page_show_num
    
    
            if page_end >= page_totle:
                page_end = page_totle
                page_start = page_totle - page_show_num +1
    
            self.page_start = page_start
            self.page_end = page_end
    
        @property               #静态属性,调用的时候可以省略括号
        def ID_start(self):     #当前页开始数据ID
            return (self.page-1) * self.data_per_page
            
            
    
        @property
        def ID_end(self):
            return(10 * self.page)
    
    
    
        def page_html(self):
            html_begin = '<nav aria-label="Page navigation"> <ul class="pagination">'
    
            last_page = self.page-1 if self.page > 1 else 1
    
            if last_page == 1:
                html_last = """
                <li> 
                <a href="{0}?page={1}">
                <span aria-hidden="true">&laquo;</span>
                </a>
                </li>""".format(self.url_prefix,last_page)
            
            else:
                html_last = """
                <li>
                <a href="{0}?page={1}" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
                </a>
                </li>""".format(self.url_prefix,last_page)
    
    
            page_cut_html = "<li><a href='{}?page=1'>首页</a></li>".format(self.url_prefix)  #html开始为跳转首页标签
            
            for i in range(self.page_start,self.page_end+1):
                page_cut_html += """
                <li><a href='{0}?page={1}'>{1}</a></li>""".format(self.url_prefix,i)
    
            page_cut_html += "<li><a href='{0}?page={1}'>尾页</a></li>".format(self.url_prefix,self.page_totle)
    
            html_end = """
            <li>
            <a href="{0}?page={1}" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
            </a>
            </li></ul></nav>""".format(self.url_prefix,self.page_end)
    
    
            page_html = html_begin + html_last + page_cut_html + html_end
            
            return mark_safe(page_html)
    /My_util/PageCut.py

    和前面的一章里的分页的代码不同的地方就是修改了一下路径拼接的地方,url_prefix直接传过来的就是当前展示的路径,然后加上参数?page就行了。

    然后对应的list视图里要大概修改一下,思路是添加下面的代码

    1 page = int(request.GET.get('page',1))
    2 
    3 data_totle = all_data.count()
    4 page_cut = Page_Cut(page=page,url_prefix=self.get_list_url() ,data_totle=data_totle)
    5 cut_html = page_cut.page_html
    6 
    7 cut_data = all_data[page_cut.ID_start:page_cut.ID_end]

    也就是生成一段html代码,添加到模板中。

    然后就搞定了!

     主要看地址栏里的URL。

     带有参数的分页效果

     在页面里可以看一下分页按钮的pref属性,我们是写成固定的了,只包含了page这个必须的参数。

    参考一下博客园里的检索时候对结论的分页

     注意一下URL,这里的URL里是带有filter结论的(filter的检索功能我们以后会讲到,这里主要讲分页的时候怎么添加pag以外的参数)

    其实思路就是我们在视图中把request.GET作为参数发送给Page_Cut。因为request.GET中包含了是以QuerySet的方式包含了参数。

    比方我们想查询id大于2,价格小于100的第二页,url的样式大概是这样的

    http://127.0.0.1:8000/Xadmin/CRUD/books/?page=2&id_gt=2&price_lt=100

    然后我们打印一下request.GET

    <QueryDict: {'page': ['2'], 'id_gt': ['2'], 'price_lt': ['100']}>

    可以看出来这个样式

    QuerySet对象有一个方法可以把整个字典拼成URL的形式

    print('GET:',request.GET)
    print('GET.encode:',request.GET.urlencode())
    
    ##########输出#########
    GET: <QueryDict: {'page': ['2'], 'id_gt': ['2'], 'price_lt': ['100']}>
    GET.encode: page=2&id_gt=2&price_lt=100

    所以就可以用这个方法来在page_cut里生成html标签的时候追加所有的参数,其实这样更简单,只需要在生成html的a标签的时候吧GET里的page值一改就行了。

    下面就是修改后的带有参数传递的分页代码

    from django.utils.safestring import mark_safe
    from copy import deepcopy
    
    
    class Page_Cut():
        def __init__(self,page,url_prefix,data_totle,param,data_per_page=10,page_show_num=11):
            """
            :param: page:当前页码
            :url_prefix:url前缀
            :data_totle:总数据量
            :date_per_page:每页显示数据条数,默认值为10
            :page_show_num:显示的分页数量,默认值为11
            """
            self.param = deepcopy(param)
            
            self.url_prefix = url_prefix  #url前缀
            page_totle,m = divmod(data_totle,data_per_page)
            page_totle = page_totle if not m else page_totle +1    #计算总页码数
            self.page_totle = page_totle
    
            self.page_show_num = page_show_num if page_show_num < self.page_totle else self.page_totle  #显示最大页码数
    
            self.data_per_page = data_per_page
    
            page = 1 if page<1 else page
            page = page_totle if page>page_totle else page
    
            self.page = page
    
            
    
            if page_totle < page_show_num:
                page_show_num = page_totle
    
            page_half = page_show_num // 2                #中间页码数
    
            page_start = page - page_half
            page_end = page + page_half 
    
            if page_start <= 1:
                page_start = 1
                page_end = page_show_num
    
    
            if page_end >= page_totle:
                page_end = page_totle
                page_start = page_totle - page_show_num +1
    
            self.page_start = page_start
            self.page_end = page_end
    
        @property               #静态属性,调用的时候可以省略括号
        def ID_start(self):     #当前页开始数据ID
            return (self.page-1) * self.data_per_page
            
            
    
        @property
        def ID_end(self):
            return(10 * self.page)
    
    
    
        def page_html(self):
            print(self.param)
            html_begin = '<nav aria-label="Page navigation"> <ul class="pagination">'
    
            last_page = self.page-1 if self.page > 1 else 1
    
            if last_page == 1:
                self.param['page'] = last_page
                html_last = """
                <li> 
                <a href="{0}?{1}">
                <span aria-hidden="true">&laquo;</span>
                </a>
                </li>""".format(self.url_prefix,self.param.urlencode())
            
            else:
                html_last = """
                <li>
                <a href="{0}?{1}" aria-label="Previous">
                <span aria-hidden="true">&laquo;</span>
                </a>
                </li>""".format(self.url_prefix,self.param.urlencode())
    
            self.param['page'] = 1
            page_cut_html = "<li><a href='{}?{}'>首页</a></li>".format(self.url_prefix,self.param.urlencode())  #html开始为跳转首页标签
            
            for i in range(self.page_start,self.page_end+1):
                self.param['page'] = i
                page_cut_html += """
                <li><a href='{0}?{1}'>{2}</a></li>""".format(self.url_prefix,self.param.urlencode(),i)
    
            self.param['page'] = self.page_totle
            page_cut_html += "<li><a href='{0}?{1}'>尾页</a></li>".format(self.url_prefix,self.param.urlencode())
    
    
            self.param['page'] = self.page_end
            html_end = """
            <li>
            <a href="{0}?{1}" aria-label="Next">
            <span aria-hidden="true">&raquo;</span>
            </a>
            </li></ul></nav>""".format(self.url_prefix,self.param.urlencode())
    
    
            page_html = html_begin + html_last + page_cut_html + html_end
            
            return mark_safe(page_html)
    My_util/PageCut.py

    要注意的是我们在传参数的时候用了深拷贝。具体原因也就不用解释了,Django里的源代码里应该是对request.GET做了保护,正常情况下防止变量被污染是不能更改的,所以我们需要用deepcopy重新复制一份。

    或者用.copy()的方法浅拷贝复制一份。

    初步的分页功能就完成了。 

  • 相关阅读:
    jquery 操作单选框,复选框,下拉列表实现代码
    使用NewtonSoft.JSON.dll来序列化和发序列化对象
    c# HttpWebRequest与HttpWebResponse 绝技
    从新浪微博的改版谈网页重构
    选择GET还是POST?
    ckeditor3.0.1上传图片功能
    EM算法入门相关文章翻译与总结3
    EM算法入门相关文章翻译与总结2
    EM算法入门相关文章翻译与总结1
    PLSA中的EM算法
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/13510740.html
Copyright © 2020-2023  润新知