最新消息:欢迎光临 魔力 • Python!大家可以点开导航菜单中的【学习目录】,这个目录类似图书目录,更加方便学习!

Django项目中使用自带的分页功能

Django教程 小楼一夜听春语 9798浏览 0评论

最近在项目中使用到了Django自带的分页功能,并结合Bootstrap的分页样式制作了分页条,在这里把使用心得和大家做一下分享。

分页功能效果如下图:

使用Django自带的分页功能,我们可以直接定义视图时继承“ListView”类,并设置相关类变量。

class OrderView(ListView):
    model = Order  # 模型类
    template_name = 'order.html'  # 模板名称
    paginate_by = 20  # 每页数量

当完成上述代码后,我们就可以使用Django自带的分页功能了。

分页条模板代码如下:

<ul class="pagination pull-right"> <!--如果有前一页-->
    {% if page_obj.has_previous %} <!--如果有前一页-->
        <li><a href="./?page=1">首页</a></li><!--链接到首页-->
        <li><a href="./?page={{ page_obj.previous_page_number }}">&laquo;</a></li> <!--链接到前一页页码-->
    {% else %}<!--否则-->
        <li class="disabled"><a>首页</a></li> <!--禁用首页按钮-->
        <li class="disabled"><a>&laquo;</a></li> <!--禁用前一页按钮-->
    {% endif %}
    {% for page_number in paginator.page_range %} <!--遍历页码范围-->
        {% if page_number != page_obj.number %} <!--如果页码与当前页页码不相同-->
            <li><a href="./?page={{ page_number }}">{{ page_number }}</a></li> <!--生成页码并添加链接-->
        {% else %}
            <li class="active"><a>{{ page_number }}</a></li> <!--否则,呈现激活样式-->
        {% endif %}
    {% endfor %}
    {% if page_obj.has_next %} <!--如果有下一页-->
        <li><a href="./?page={{ page_obj.next_page_number }}">&raquo;</a></li> <!--链接到下一页页码-->
        <li><a href="./?page={{ paginator.num_pages }}">尾页</a></li> <!--链接到尾页-->
    {% else %}<!--否则-->
        <li class="disabled"><a>&raquo;</a></li> <!--否则禁用下一页按钮-->
        <li class="disabled"><a>尾页</a></li> <!--禁用尾页按钮-->
    {% endif %}
</ul>

上方代码中,有一些关键的内容如下:

  • paginator.page_range:页码范围(迭代对象)
  • page_obj.has_previous:是否存在前一页(布尔值)
  • page_obj.has_next:是否存在下一页(布尔值)
  • page_obj.previous_page_number:前一页的页码(数值)
  • page_obj.next_page_number:下一页的页码(数值)
  • page_obj.number:当前页的页码(数值)
  • paginator.num_pages:页面总数量(数值)

如果只是想实现首页、尾页、上一页、下一页以及根据页码翻页的功能,上面的代码就能够满足需求了。

不过,往往我们的项目中会包含很多数据,分页总数量很多,这个时候分页条会变得很长。

所以,我们需要在分页条中只显示部分页码,就像效果图一样,无论当前为第几页,且无论有多少页码,分页条上不超过9个数字页码,规则如下:

  • 当前页码为前4页并且读取到的页码为前9页时,分页条上加载读取到的页码。
  • 当前页码为后4页并且读取到的页码为后9页时,分页条上加载读取到的页码。
  • 读取到的页码为当前页码前4页与后4页之间的页码时,分页条上加载读取到的页码。

根据以上规则,我们可以添加相应的条件判断,让页码有条件的在分页条上显示出来。

这里我们需要在模板中对页码进行加减法运算,需要用到Django自带的过滤器“add”。

过滤器“add”的使用方法为:{{ 变量|add:”x”}},能够对变量进行加减一定数值的操作,“x”表示加减的数值,正数为加法,负数为减法。

所以上面的规则写成条件如下:

  • page_obj.number < 5 and page_number < 10
  • page_number|add:”9″ > paginator.num_pages and page_obj.number|add:”4″ > paginator.num_pages
  • page_number|add:”5″ > page_obj.number and page_number|add:”-5″ < page_obj.number

这三个条件是“或者”的关系,我们可以在模板代码中使用“or”进行连接。

新的分页条代码如下:

<ul class="pagination pull-right">
    {% if page_obj.has_previous %} <!--如果有前一页-->
        <li><a href="./?page=1">首页</a></li><!--链接到首页-->
        <li><a href="./?page={{ page_obj.previous_page_number }}">&laquo;</a></li><!--链接到前一页页码-->
    {% else %}<!--否则-->
        <li class="disabled"><a>首页</a></li><!--禁用首页按钮-->
        <li class="disabled"><a>&laquo;</a></li><!--禁用前一页按钮-->
    {% endif %}
    {% for page_number in paginator.page_range %}<!--遍历页码范围-->
        {% if page_number != page_obj.number %}<!--如果页码与当前页页码不相同-->
            {% if page_obj.number < 5 and page_number < 10 or page_number|add:"9" > paginator.num_pages and page_obj.number|add:"4" > paginator.num_pages or page_number|add:"5" > page_obj.number and page_number|add:"-5" < page_obj.number %}
                <li><a href="./?page={{ page_number }}">{{ page_number }}</a></li><!--生成页码并添加链接-->
            {% endif %}
        {% else %}
            <li class="active"><a>{{ page_number }}</a></li><!--否则,呈现激活样式-->
        {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}<!--如果有下一页-->
        <li><a href="./?page={{ page_obj.next_page_number }}">&raquo;</a></li><!--链接到下一页页码-->
        <li><a href="./?page={{ paginator.num_pages }}">尾页</a></li><!--链接到尾页-->
    {% else %}<!--否则-->
        <li class="disabled"><a>&raquo;</a></li><!--否则禁用下一页按钮-->
        <li class="disabled"><a>尾页</a></li><!--禁用尾页按钮-->
    {% endif %}
</ul>

对于一般的列表分页来说,上面的代码已经能够满足需求。

不过,如果我们通过“GET”方式传递参数,对列表进行筛选排序的操作时,如果不对分页条代码进行处理,那么翻页之后会发现筛选排序失效。

因为,我们的分页条中组织的翻页链接没有带上相应的参数。

例如,我们筛选当日订单时,URL为:http://www.domain.com/admin/order/?create_time=today。

而点击翻页按钮之后(例如翻到第2页),此时URL为:http://www.domain.com/admin/order/?page=2。

这时丢失了参数“create_time=today”,所以我们翻页后,列表是所有订单,而不是当日订单。

那么,怎么在设置分页链接的时候,带有前一次URL中的参数呢?

我们可以在视图中通过“request.META.get(‘QUERY_STRING’, None)”获取上一次的参数,然后传入模板中。

示例代码:

query_string = re.sub(r'page=[0-9]+[&]?', '', request.META.get('QUERY_STRING', None))  # 替换掉请求参数中的页码参数及其后方的“&”符号
if query_string:  # 如果还有其他参数
    query_string = '&' + query_string # 将其他参数前方添加“&”符号

通过上方的代码我们就能够获得上一次URL中的请求参数,然后将获取到的请求参数和列表筛选结果一起传递给模板就可以了。

最终模板中分页条代码为:

<ul class="pagination pull-right">
    {% if page_obj.has_previous %} <!--如果有前一页-->
        <li><a href="./?page=1{{ query_string }}">首页</a></li><!--链接到首页-->
        <li><a href="./?page={{ page_obj.previous_page_number }}{{ query_string }}">&laquo;</a></li><!--链接到前一页页码-->
    {% else %}<!--否则-->
        <li class="disabled"><a>首页</a></li><!--禁用首页按钮-->
        <li class="disabled"><a>&laquo;</a></li><!--禁用前一页按钮-->
    {% endif %}
    {% for page_number in paginator.page_range %}<!--遍历页码范围-->
        {% if page_number != page_obj.number %}<!--如果页码与当前页页码不相同-->
            {% if page_obj.number < 5 and page_number < 10 or page_number|add:"9" > paginator.num_pages and page_obj.number|add:"4" > paginator.num_pages or page_number|add:"5" > page_obj.number and page_number|add:"-5" < page_obj.number %}
                <li><a href="./?page={{ page_number }}{{ query_string }}">{{ page_number }}</a></li><!--生成页码并添加链接-->
            {% endif %}
        {% else %}
            <li class="active"><a>{{ page_number }}</a></li><!--否则,呈现激活样式-->
        {% endif %}
    {% endfor %}
    {% if page_obj.has_next %}<!--如果有下一页-->
        <li><a href="./?page={{ page_obj.next_page_number }}{{ query_string }}">&raquo;</a></li><!--链接到下一页页码-->
        <li><a href="./?page={{ paginator.num_pages }}{{ query_string }}">尾页</a></li><!--链接到尾页-->
    {% else %}<!--否则-->
        <li class="disabled"><a>&raquo;</a></li><!--否则禁用下一页按钮-->
        <li class="disabled"><a>尾页</a></li><!--禁用尾页按钮-->
    {% endif %}
</ul>

 

转载请注明:魔力Python » Django项目中使用自带的分页功能

头像
发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网站 (可选)

网友最新评论 (1)

  1. 头像
    小楼老师好厉害
    产品大师5年前 (2018-12-13)回复