Django Pagination 完善分页

Django Pagination 简单分页 中,我们实现了一个简单的分页导航效果。但效果有点差强人意,我们只能点上一页和下一页的按钮进行翻页。比较完善的分页效果应该像下面这样,但想实现这样一种效果,Django Pagination 内置的 API 已无能为力。本文将通过拓展 Django Pagination 来实现下图这样比较完善的分页效果。

高级分页效果图

分页效果概述

一个比较完善的分页效果应该具有以下特性,就像上图展示的那样,很多网站都采用了类似这种的分页导航方式。

  • 始终显示第一页和最后一页。
  • 当前页码高亮显示。
  • 显示当前页码前后几个连续的页码。
  • 如果两个页码号间还有其它页码,中间显示省略号以提示用户。

拓展 Pagination

在此之前,我们已将首页文章列表的视图函数转为了类视图,并且使用了类视图 ListView 中已经为我们写好的分页代码来达到分页的目的(详情请查看文章开头处给出的链接)。为了实现如下所展示的分页效果,接下来就需要在 ListView 的基础上进一步拓展分页的逻辑代码。

高级分页效果图

先来分析一下导航条的组成部分,可以看到整个分页导航条其实可以分成 七个部分:

  1. 第 1 页页码,这一页需要始终显示。
  2. 第 1 页页码后面的省略号部分。但要注意如果第 1 页的页码号后面紧跟着页码号 2,那么省略号就不应该显示。
  3. 当前页码的左边部分,比如这里的 3-6。
  4. 当前页码,比如这里的 7。
  5. 当前页码的右边部分,比如这里的 8-11。
  6. 最后一页页码前面的省略号部分。但要注意如果最后一页的页码号前面跟着的页码号是连续的,那么省略号就不应该显示。
  7. 最后一页的页码号。

因此我们的思路是,在视图里将以上七步中所需要的数据生成,然后传递给模板并在模板中渲染显示即可。整个视图的代码如下,由于代码比较长,所以代码实现的功能直接在代码块中注释,就不在文章中进一步说明了。推荐使用大屏幕阅读器获取更好的阅读体验。

blog/views.py

class IndexView(ListView):
    model = Post
    template_name = 'blog/index.html'
    context_object_name = 'post_list'
    paginate_by = 10

    def get_context_data(self, **kwargs):
        """
        在视图函数中将模板变量传递给模板是通过给 render 函数的 context 参数传递一个字典实现的,
        例如 render(request, 'blog/index.html', context={'post_list': post_list}),
        这里传递了一个 {'post_list': post_list} 字典给模板。
        在类视图中,这个需要传递的模板变量字典是通过 get_context_data 获得的,
        所以我们复写该方法,以便我们能够自己再插入一些我们自定义的模板变量进去。
        """

        # 首先获得父类生成的传递给模板的字典。
        context = super().get_context_data(**kwargs)

        # 父类生成的字典中已有 paginator、page_obj、is_paginated 这三个模板变量,
        # paginator 是 Paginator 的一个实例,
        # page_obj 是 Page 的一个实例,
        # is_paginated 是一个布尔变量,用于指示是否已分页。
        # 例如如果规定每页 10 个数据,而本身只有 5 个数据,其实就用不着分页,此时 is_paginated=False。
        # 关于什么是 Paginator,Page 类在 Django Pagination 简单分页:http://zmrenwu.com/post/34/ 中已有详细说明。
        # 由于 context 是一个字典,所以调用 get 方法从中取出某个键对应的值。
        paginator = context.get('paginator')
        page = context.get('page_obj')
        is_paginated = context.get('is_paginated')

        # 调用自己写的 pagination_data 方法获得显示分页导航条需要的数据,见下方。
        pagination_data = self.pagination_data(paginator, page, is_paginated)

        # 将分页导航条的模板变量更新到 context 中,注意 pagination_data 方法返回的也是一个字典。
        context.update(pagination_data)

        # 将更新后的 context 返回,以便 ListView 使用这个字典中的模板变量去渲染模板。
        # 注意此时 context 字典中已有了显示分页导航条所需的数据。
        return context

    def pagination_data(self, paginator, page, is_paginated):
        if not is_paginated:
            # 如果没有分页,则无需显示分页导航条,不用任何分页导航条的数据,因此返回一个空的字典
            return {}

        # 当前页左边连续的页码号,初始值为空
        left = []

        # 当前页右边连续的页码号,初始值为空
        right = []

        # 标示第 1 页页码后是否需要显示省略号
        left_has_more = False

        # 标示最后一页页码前是否需要显示省略号
        right_has_more = False

        # 标示是否需要显示第 1 页的页码号。
        # 因为如果当前页左边的连续页码号中已经含有第 1 页的页码号,此时就无需再显示第 1 页的页码号,
        # 其它情况下第一页的页码是始终需要显示的。
        # 初始值为 False
        first = False

        # 标示是否需要显示最后一页的页码号。
        # 需要此指示变量的理由和上面相同。
        last = False

        # 获得用户当前请求的页码号
        page_number = page.number

        # 获得分页后的总页数
        total_pages = paginator.num_pages

        # 获得整个分页页码列表,比如分了四页,那么就是 [1, 2, 3, 4]
        page_range = paginator.page_range

        if page_number == 1:
            # 如果用户请求的是第一页的数据,那么当前页左边的不需要数据,因此 left=[](已默认为空)。
            # 此时只要获取当前页右边的连续页码号,
            # 比如分页页码列表是 [1, 2, 3, 4],那么获取的就是 right = [2, 3]。
            # 注意这里只获取了当前页码后连续两个页码,你可以更改这个数字以获取更多页码。
            right = page_range[page_number:page_number + 2]

            # 如果最右边的页码号比最后一页的页码号减去 1 还要小,
            # 说明最右边的页码号和最后一页的页码号之间还有其它页码,因此需要显示省略号,通过 right_has_more 来指示。
            if right[-1] < total_pages - 1:
                right_has_more = True

            # 如果最右边的页码号比最后一页的页码号小,说明当前页右边的连续页码号中不包含最后一页的页码
            # 所以需要显示最后一页的页码号,通过 last 来指示
            if right[-1] < total_pages:
                last = True

        elif page_number == total_pages:
            # 如果用户请求的是最后一页的数据,那么当前页右边就不需要数据,因此 right=[](已默认为空),
            # 此时只要获取当前页左边的连续页码号。
            # 比如分页页码列表是 [1, 2, 3, 4],那么获取的就是 left = [2, 3]
            # 这里只获取了当前页码后连续两个页码,你可以更改这个数字以获取更多页码。
            left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]

            # 如果最左边的页码号比第 2 页页码号还大,
            # 说明最左边的页码号和第 1 页的页码号之间还有其它页码,因此需要显示省略号,通过 left_has_more 来指示。
            if left[0] > 2:
                left_has_more = True

            # 如果最左边的页码号比第 1 页的页码号大,说明当前页左边的连续页码号中不包含第一页的页码,
            # 所以需要显示第一页的页码号,通过 first 来指示
            if left[0] > 1:
                first = True
        else:
            # 用户请求的既不是最后一页,也不是第 1 页,则需要获取当前页左右两边的连续页码号,
            # 这里只获取了当前页码前后连续两个页码,你可以更改这个数字以获取更多页码。
            left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]
            right = page_range[page_number:page_number + 2]

            # 是否需要显示最后一页和最后一页前的省略号
            if right[-1] < total_pages - 1:
                right_has_more = True
            if right[-1] < total_pages:
                last = True

            # 是否需要显示第 1 页和第 1 页后的省略号
            if left[0] > 2:
                left_has_more = True
            if left[0] > 1:
                first = True

        data = {
            'left': left,
            'right': right,
            'left_has_more': left_has_more,
            'right_has_more': right_has_more,
            'first': first,
            'last': last,
        }

        return data

模板中设置分页导航

接下来便是在模板中设置分页导航了,将导航条的七个部分的数据一一展现即可,示例代码如下:

{% if is_paginated %}
<div class="pagination">
  {% if first %}
    <a href="?page=1">1</a>
  {% endif %}
  {% if left %}
    {% if left_has_more %}
        <span>...</span>
    {% endif %}
    {% for i in left %}
        <a href="?page={{ i }}">{{ i }}</a>
    {% endfor %}
  {% endif %}
  <a href="?page={{ page_obj.number }}" style="color: red">{{ page_obj.number }}</a>
  {% if right %}
    {% for i in right %}
        <a href="?page={{ i }}">{{ i }}</a>
    {% endfor %}
    {% if right_has_more %}
        <span>...</span>
    {% endif %}
  {% endif %}
  {% if last %}
    <a href="?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a>
  {% endif %}
</div>
{% endif %}

多添加几篇文章,在示例中就可以看到分页效果了。要使分页导航更加美观,通过设置其 CSS 样式即可:

Django 完善分页效果

总结

本章节的代码位于:Step20: complete pagination

如果遇到问题,请通过下面的方式寻求帮助。

-- EOF --


81 条评论 / 36 人参与
DFnum26
提示下:楼上发的CSS样式需要放在base.html的<head></head>中,且用<style type="text/css"></style>包含其中CSS代码!

SamK6517433923 DFnum26

CSS可以了,感谢~


Rich

博主您好,请问如果我没有使用您的通用类视图,要如何写高级的分页功能呢? 请问能给个思路或案例嘛?非常感谢您~~~ :)


Rich Rich

哈哈 我搞定啦! 谢谢楼主啦~~  看到文章内那么多代码心里害怕了,但是其实仔细读一读是可以读懂的


庄鑫王建

楼主您好!请问分页的居中如何设置呢?我在div中使用 align="center"但是没有效果。谢谢!


jizhongwei

博主,还想没有实现当前页的页码颜色加深哦。。。。


追梦人物 [博主] jizhongwei

参考评论区的代码,自行添加 css 即可。


花_易秋
  •  是大法官
  • Image

测试样例


Me_Before丨You

sequence index must be integer, not ‘slice’ 

这是因为xrange对象不能进行slice操作,进入templatetags,将pagination_tags.py,paginate函数里的page_range = paginator.page_range改为 page_range = list(paginator.page_range)


孤云飘飘zhao

老师的思路非常好,我来顺便简化一下一些重复的代码.

def pagination_data(self, paginator, page, is_paginated):
if not is_paginated:
return {}
left_has_more = False
right_has_more = False
first = False
last = False
page_number = page.number
total_pages = paginator.num_pages
page_range = paginator.page_range
right = page_range[page_number:page_number + 2]
left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]
if right:
if right[-1] < total_pages - 1:
right_has_more = True
if right[-1] < total_pages:
last = True
if left:
if left[0] > 2:
left_has_more = True
if left[0] > 1:
first = True

郭效杨

那这样看起来只有index主页有分页啊进入标签页,类别页会调用index view中的分页吗?


双鱼幸福leon 郭效杨

分类和归档用之前那的视图类继承

class ArchivesView(IndexView)


ELI

感谢楼主的教程~

贴一下IndexView里的paginator_data函数的比较简洁的写法:

def pagination_data(self, paginator, page, is_paginated):
if not is_paginated:
return {}
left = []
right = []
left_has_more = False
    right_has_more = False
    first = False
last = False

page_number = page.number
total_pages = paginator.num_pages
page_range = paginator.page_range

left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:
(page_number - 1) if (page_number - 1) > 0 else 0]
right = page_range[page_number:page_number + 2]

if right:
if right[-1] < total_pages:
last = True
        if right[-1] < total_pages - 1:
right_has_more = True
    if left:
if left[0] > 1:
first = True
        if left[0] > 2:
left_has_more = True

    data = {'left': left,
    'right': right,
            'left_has_more': left_has_more,
     'right_has_more': right_has_more,
      'first': first,
            'last': last,}

return data

amou1758 ELI

NICE  很好使


Fossen Wang

分享一段css代码用于美化分页,效果类似于开头的示例:

.pagination {margin-top: 25px; text-align: center;}
.pagination a {
display: inline-block;
line-height: 38px;
padding: 0 15px;
margin-right: 4px;
text-align: center;
background-color: #fff;
user-select: none;
cursor: pointer;
font-size: 14px;
border: 1px solid #d7dde4;
border-radius: 4px;
transition: all .2s ease-in-out;
}
.pagination a:hover {
color: #A161BF;
border: 1px solid #A161BF;
}
.pagination .current-page {color: white; background-color: #A161BF;}
.pagination .current-page:hover {
color: white;
border: 1px solid #A161BF;
}
.pagination span {
display: inline-block;
font-size: 20px;
line-height: 38px;
padding: 0 8px;
margin-right: 4px;
}

还需要改写模板中的一行代码:

<a href="?page={{ page_obj.number }}" style="color: red">{{ page_obj.number }}</a>

改为:

<a class="current-page" href="?page={{ page_obj.number }}" >{{ page_obj.number }}</a>

5岁月神偷5 Fossen Wang

可以用,谢谢


谢亚波 Fossen Wang

大哥,这段css代码,贴在哪个位置,原谅小弟不才,问这么简单的问题。


谢亚波 5岁月神偷5

大哥,这段css代码,贴在哪个位置,原谅小弟不才,问这么简单的问题。


Me_Before丨You 谢亚波

自定义style


zlh95 Fossen Wang

骚气紫色高亮


花_易秋 Fossen Wang

感谢啊,这个颜色适合我,骚气紫!


庄鑫王建 Fossen Wang

您好!请问分页的居中如何设置呢?我在div中使用 align="center"但是没有效果。谢谢!


Huangbo 庄鑫王建

在<div class="pagination">外面加一层:<div class="text-center">


xuyy2 谢亚波

越俎代庖,回答一下;可以复制到custom.css的后面;浏览器要清除缓存,刷新,就能看到效果了


Stallionshell

博主,在调用父类的方法的时候,super是不是需要添加一下参数?

         context = super().get_context_data(**kwargs)

改为  context = super(IndexView,self).get_context_data(**kwargs)

不然的话 可能出现index界面无法读取文章的情况,不知道是不是python或者django环境版本的问题。这是我测试的时候出现的一个bug


Stallionshell Stallionshell

好像不是这个的问题,我又出现了这个bug  尴尬


追梦人物 [博主] Stallionshell

这是 python3 的写法,python2需要使用父类和self作为参数。


point6013

出现了一个问题,假如说是总共两页的时候,按照您的代码,浏览第二页的时候,页码1是不显示的,我觉得应该修改一下

elif page_number == total_pages:  
     left = page_range[(page_number - 3)if (page_number - 3) > 0 else 0:page_number - 1]
     if left[0] > 2:
         left_has_more = True
     if left[0] > 1:
         first = True

这个地方,如果是总共两页的话,left应该是left=page_range[0:1],此时page_range=[1,2],即left=[1],这个时候如果去比较left[0]与1的大小的话,first=False了,我觉得应该修改此处的代码。不知道我的逻辑对不对


追梦人物 [博主] point6013

可能吧,但我当时测试的时候好像没有发现问题,你测试一下应该就知道了。有问题的话修改一下逻辑即可。


point6013 追梦人物 [博主]

谢谢博主,抽出宝贵的上班时间回复消息


cuitongji

博主你好,完善页码之后出现如下错误是为什么呢?

context = super().get_context_data(**kwargs)


zhb1207 cuitongji

你是Python2还是3?


cuitongji zhb1207

我该环境之后没问题了,谢谢博主!


zhb1207 cuitongji

不用客气,我不是博主^_^


Faraday179

博主好,  blog/views中添加了分页后,  执行127.0.0.1:8000显示以下错误;

TypeError at /'NoneType' object is not iterable


具体错误如下,  表中有13条数据 , 设置了paginate_by = 2, 不明白为什么pagination_data = None ? 谢谢指点 

/blogproject/blog/views.py in get_context_data

28.  context.update(pagination_data)

Local Vars

Variable         Value

__class__    <class 'blog.views.IndexView'> 

context        {'is_paginated': True, 'object_list': <QuerySet [<Post: r234223>, <Post: kjjadf>]>, 'page_obj': <Page 1 of 7>, 'paginator': <django.core.paginator.Paginator object at 0x1097d53c8>, 'post_list': <QuerySet [<Post: r234223>, <Post: kjjadf>]>, 'view': <blog.views.IndexView object at 0x1097d5358>} 

is_paginated  True 

kwargs   {} 

page    <Page 1 of 7> 

pagination_data  None 

paginator    <django.core.paginator.Paginator object at 0x1097d53c8> 

self           <blog.views.IndexView object at 0x1097d5358


追梦人物 [博主]
这通常是你的 url 写错了,对比一下文章中的,仔细一点。

usher
Error during template rendering

In template D:\Django\blogproject\templates\base.html, error at line 15
Reverse for 'category' with arguments '('',)' not found. 1 pattern(s) tried: ['category/(?P[0-9]+)/$']
5
6 Black & White
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
博主报了这个错误,这是哪错了?

追梦人物 [博主] usher

这通常是你的 url 写错了,对比一下文章中的,仔细一点。


usher 追梦人物 [博主]

把+改成*就对了==


一条具有时间跨度的单身狗1
# 首页类视图
class IndexView(ListView):
model = Article
template_name = 'blog/index.html'
context_object_name = 'art_list'
ordering = '-art_ctime'
paginate_by = 1

def get_context_data(self, **kwargs):
# 获取父类传递的给模板的字典
context = super().get_context_data(**kwargs)

# 将分页导航条的模板变量更新到context 中
context.update(pagination_data)

# 将 context 返回,以便于调用新的 context 来渲染模板
return context

def pagination_data(self, paginator, page, is_paginated):
if not is_paginated:
# 如果没有分页,就不需要导航条,返回空字典
return {}

# 当前页面左边的页码,默认空
left = []

# 当前页面右边的页码,默认空
right = []

# 标识第一页后面是否需要显示省略号
left_has_more = False

# 标识最后一页前是否需要省略号
right_has_more = False

# 标记是否显示第一页,如果左边连续的页码中包含第一页,则无需显示第一页
first = False

# 标记是否显示最后一页
last = False

# 获取当前访问的页数
page_number = page.number

# 获取分页后的总页数
total_pages = paginator.num_pages

# 获取整个分页页码表,比如分 3 页则是 [1, 2, 3]
page_range = paginator.page_range

# 切割页数
cut_page = 2

# 如果所在页面在第一页,则判断后面页数
if page_number == 1:
right = page_range[page_number:(page_number + cut_page)]

if total_pages > (right[-1] + 2):
right_has_more = True

if total_pages > right[-1]:
last = True
# 如果在最后一页
elif page_number == total_pages:
left = page_range[(-(cut_page + 1)):(-1)]

if left[0] > 2:
left_has_more = True

if left[0] > 1:
first = True
# 如果即不再第一页也不再最后一页
else:
# 判断左边
left = page_range[(-((total_pages - page_number + 1) + cut_page)):(-(total_pages - page_number + 1))]
if left[0] > 2:
left_has_more = True

if left[0] > 1:
first = True

# 判断右边
right = page_range[page_number:(page_number + cut_page)]

if total_pages > (right[-1] + 1):
right_has_more = True

if total_pages > (right[-1]):
last = True

data = {
'left': left,
'right': right,
'left_has_more': left_has_more,
'right_has_more': right_has_more,
'first': first,
'last': last,

return data

这是我写的,有些地方和博主的不一样,是自定义的,测试如果有问题的可以参考。有些地方分开可能好理解一点。

一条具有时间跨度的单身狗1 一条具有时间跨度的单身狗1
data 字典那里复制的时候少了个 }

-陈思煜
我感觉作者写的代码逻辑有问题,但是运行却能完美运行,这是DJango里面自带的功能吗?比如
if page_number == 1:
right = page_range[page_number:page_number + 2]
当页面只有2页的话,最后right的值却是2和3 但是page_range是没有这个值的

-陈思煜 -陈思煜
还有比如:
else:
left = page_range[(page_number - 3) if (page_number - 3) > 0 else 0:page_number - 1]
right = page_range[page_number:page_number + 2]
当请求到倒数第二页时,right的最大那个比倒数第一页的值还大1
但还是没报错

-陈思煜 -陈思煜
看来是我对切片理解不够深了,试了一下,超出范围的切片后,python止取出有效的数值

皮皮欧呢
博主,我现在遇到一个问题是:在admin中添加post文章时,在选择tag和category时他们给出的选项是tag object和category object,但是我想要的是tag或者category里边的(Java,Python,数据结构......)等,试了几个方法还是不行

追梦人物 [博主] 皮皮欧呢
你需要为 model 定义 __str__ 方法,详情见之前关于model 部分的教程。

zengzhengrong
博主,我没用类方法写视图,没有继承ListView,没有page_obj、is_paginated,这两个字典。

追梦人物 [博主] zengzhengrong
可以参考着上一篇的内容自己创建,明白了运行原理自己写也不难。

LeBron-Raymond-Anson
博主!我问个问题,我按照你的博文代码一步一步理解敲的,也和GitHub上的代码核对过了,并无出入,这么显示不了上一页和下一页的按钮呢

追梦人物 [博主] LeBron-Raymond-Anson
是不是测试地数据太少不足以分页呀?

JustBreaking
亲测我觉得博主的代码没问题
只是我用的py2.7 page_range返回的是一个迭代器,要用list转化一下就好。
至于right[page_num:page_num+2] 和left[]的切片,顶多为空(当前页是最后一页),但是即使超出列表的index也不会报错。这样写right/left列表的长度可能为0,可能为1,也可能为2。比较灵活。
感谢博主能提供这么好的教程!

yeliang
使用python2.7的同学super().get_context_data(**kwargs)这里会报错,应该要改下super(IndexView, self).get_context_data(**kwargs)。
使用2.7还需要改写的地方是paginator.page_range,会得到一个xrange的生成器,这个xrange是不能切片的,但是3.6版本没有xrange了,xrange已经变成range,所以可以切片

追梦人物 [博主] yeliang
嗯,对 py2 的兼容我没有考虑了。

JustBreaking yeliang
没切片,用list(page_range)就好勒

Bivectorfoil 追梦人物 [博主]
首先感谢博主精彩的教程,目前我有一个问题,在将index视图函数用类改写以后,访问主页(index.html)却得到这样的错误:TemplateDoesNotExist: blogs/post_list.html,(blogs是我的app名称),虽然我使用的是py2,但我已经按上面其他同学给出的方法仔细地重写了有关super方法处和page_range处的代码,但仍然得到这个错误,模板文件的位置也已经做了检查,奇怪的是,用同样方法复写的Detail ,archives和category等视图函数均可以访问成功,在此请教博主和各位同学,希望能够得到解答,多谢!完整的报错信息如下:

Traceback (most recent call last):
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
response = get_response(request)
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 217, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 215, in _get_response
response = response.render()
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/template/response.py", line 107, in render
self.content = self.rendered_content
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/template/response.py", line 82, in rendered_content
template = self.resolve_template(self.template_name)
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/template/response.py", line 64, in resolve_template
return select_template(template, using=self.using)
File "/home/zvector/BlogLearn/venv/local/lib/python2.7/site-packages/django/template/loader.py", line 53, in select_template
raise TemplateDoesNotExist(', '.join(template_name_list), chain=chain)
TemplateDoesNotExist: blogs/post_list.html

追梦人物 [博主] Bivectorfoil
把 index.html 改为 post_list.html

Bivectorfoil 追梦人物 [博主]
感谢博主,目前访问主页成功,访问其他(归档,分类等)也成功了,但我有个疑问,这样修改的原理是什么?我仔细对照过博主github教程上的代码,主页的文件名称并不需要修改(为index.html),这是为何?这样的改动会不会太大,因为相应的其他地方需要用到index.html文件的地方也需要修改。再次感谢博主的解答。

追梦人物 [博主] Bivectorfoil
只是为了方便,所以各个视图函数都渲染了 index.html,如果你的模板不同的话,你可以创建不同的模板,不同视图渲染不同模板就可以了。

Annihilater JustBreaking

感谢,猜到了是2.7兼容的问题还没找出来,幡然醒悟


qiqiming
pagination_data 这个函数感觉博主写的逻辑很严谨,但是是不是有一个小小的问题, rigth并不会取到1, 所以如果当前页面为第一页时, 就没有页码1了, 感觉把right = page_range[page_number:page_number + 2],改为right = page_range[page_number - 1:page_number + 2]是不是好一些。

qiqiming qiqiming
以上说的是page_num == 1时

追梦人物 [博主] qiqiming
应该可以取到 1 吧?我博客用的这段代码,使用下来没发现 bug。你这样修改以后测试有问题么?

qiqiming 追梦人物 [博主]
想了一下逻辑,page_num == 1时right = page_range[page_num: page_num + 2] 无论如何取不到1,因为page_range[0]为1, 而此时page_num=1, 取到的是2, first此时也一直为false取不到1。亲测也是如此。

qiqiming qiqiming
当然不排除我可能有bug。。

追梦人物 [博主] qiqiming
其实我现在搞不清我写的代码了,总之目前来看运行上没什么问题,也就懒得管了。当然我这个代码里可能有些重复,有可以优化的地方。

yeliang qiqiming
我可以给您解释下,page_num==1的时候 first本来就是要false的,您可能还没有明白这个参数的意思,frist的意义是“标示是否需要显示第一页的页码号”,您现在当前页面是第一页的情况,只要判断right和last以及right_has_more这些参数即可,你看看index.html模板下的代码就知道了

yeliang 追梦人物 [博主]
这个代码逻辑性已经非常号了
if page_number == 1:
# 用户请求的是第一页的数据
# 页码的右边部分为[2,3],左边和右边的连续页码都是加2
right = page_range[1:3]
不过我觉的直接写[1:3]会更加简洁明了

追梦人物 [博主] yeliang
必须从 page range 里截取吧?因为有时候只有两页。

追梦人物 [博主] yeliang
嗯,我明白了,第一页时直接用数字代替就可以了。

yeliang 追梦人物 [博主]
没事的就是超过这个范围也不会有异常的。我都测试过了

qiqiming yeliang
我知道first的意思, 我的意思是1不会显示, 因为right里面没有。。。。。

qiqiming yeliang
page_range[1] = 2

yeliang qiqiming
当你当前页码为1的时候,right肯定不能包含1啊,这位大哥,right的意思是你当前页码右边显示的两个页码数组,怎么可能有1啊??你当前页码是1啊

追梦人物 [博主] qiqiming
是的 1不会显示,在模板中显示的是 current page,而实际就是 1

qiqiming yeliang
我知道了,理解不同

qiqiming qiqiming
找出问题了,我已经修改了,感谢讨论

Annihilater qiqiming

楼上有人解答了,切片取到有效值为止


Annihilater Annihilater

好吧,说的不是一个问题我理解错了


追梦人物 [博主]
类似的,这个分页方法是通用的,稍加修改可以用于任何需要分页的地方。

corebym
请问用户profile页面可以做吗? 用户follow,私信、动态等功能

追梦人物 [博主] corebym
这个分页方法是通用的,稍加修改可以用于任何需要分页的地方。