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

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

分页功能效果如下图:

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

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

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

分页条模板代码如下:

{% if page_obj.has_previous %}

首页

«

{% else %} 首页

«

{% endif %} {% for page_number in paginator.page_range %} {% if page_number != page_obj.number %} {{ page_number }}

{% else %} {{ page_number }}

{% endif %} {% endfor %} {% if page_obj.has_next %} »

尾页

{% else %} »

尾页

{% endif %}

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

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

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″

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

新的分页条代码如下:

{% if page_obj.has_previous %} 首页

«

{% else %} 首页

«

{% endif %} {% for page_number in paginator.page_range %} {% if page_number != page_obj.number %}{% if page_obj.number 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_number }}

{% endif %}{% else %} {{ page_number }}

{% endif %} {% endfor %} {% if page_obj.has_next %} »

尾页

{% else %} »

尾页

{% endif %}

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

不过,如果我们通过“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中的请求参数,然后将获取到的请求参数和列表筛选结果一起传递给模板就可以了。

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

{% if page_obj.has_previous %}

{{ query_string }}">首页

{{ query_string }}">«

{% else %} 首页

«

{% endif %} {% for page_number in paginator.page_range %} {% if page_number != page_obj.number %} {% if page_obj.number 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"

{{ query_string }}">{{ page_number }}

{% endif %} {% else %} {{ page_number }}

{% endif %} {% endfor %} {% if page_obj.has_next %}

{{ query_string }}">»

{{ query_string }}">尾页

{% else %} »

尾页

{% endif %}

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20181127A0WEX800?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券