3

目前,我正在使用 Django 的 object_list 来处理分页。如果您在听到我的问题后认为我需要它,我很高兴转到正确的 Paginator() 类:

在主页上,我想分页7,但在所有其他页面上,我想分页10

我该怎么做呢?我真的无法理解它。我最接近让它工作的结果导致一整页的结果被遗漏了,所以显然我不希望这样。

我会非常感谢任何答案。如果您需要更多信息,请告诉我。非常感谢。

4

4 回答 4

7

就像在主页视图中一样,在其他任何地方from django.core.paginator import Paginator创建一个分页器对象。然后在任何一种情况下,在您用来呈现模板的上下文中绑定。在任何一种情况下都会被适当地设置(你似乎说这是你正在使用的方法,对吧?也就是说,这就是你所说的“Django's object_list”的意思吗?)。p = Paginator(thestuff, 7)p = Paginator(thestuff, 10)pp.object_list

Django文档有很好的细节和示例(假设您使用的是 1.0 或更高版本)。如果你不能让它工作,你能告诉我们(一个仍然失败的简化版本)你的模板和视图代码吗?

编辑:现在已经清楚地显示了问题,我认为应该通过子类化 Django 的核心分页器来解决,如下所示:

from django.core.paginator import Paginator, Page

class MyPaginator(Paginator):

  def __init__(self, **kw):
    self.deltafirst = kw.pop('deltafirst', 0)
    Paginator.__init__(self, **kw)

  def page(self, number):
    "Returns a Page object for the given 1-based page number."
    number = self.validate_number(number)
    if number == 1:
      bottom = 0
      top = self.per_page - self.deltafirst
    else:
      bottom = (number - 1) * self.per_page - self.deltafirst
      top = bottom + self.per_page
    if top + self.orphans >= self.count:
      top = self.count
    return Page(self.object_list[bottom:top], number, self)

现在完全按照上面的文本使用 MyPaginator,示例显示了 Django 自己的用法,除了在创建它时,使用额外的命名参数deltafirst=3使第一页 3 比正常的每页长度(10)短。因此,您将使用标称长度为 10 但 deltafirst 为 3 的单个分页器,以使第一页 3 比所有其他页面短。

(可能存在问题,validate_number但我不确定它们是否会出现——如果出现了,那么 MyPaginator 也需要覆盖该方法)。

最新版本的 Django 更新

由于没有考虑位置参数,上面的代码会出错,并且num_pages还需要重写以允许正确显示最后一页:

from math import ceil


class MyPaginator(Paginator):
    
    def __init__(self, *args, **kw):
        self.deltafirst = kw.pop('deltafirst', 0)
        super().__init__(*args, **kw)
    
    def page(self, number):
        number = self.validate_number(number)
        if number == 1:
            bottom = 0
            top = self.per_page - self.deltafirst
        else:
            bottom = (number - 1) * self.per_page - self.deltafirst
            top = bottom + self.per_page
        if top + self.orphans >= self.count:
            top = self.count
        return self._get_page(self.object_list[bottom:top], number, self)

    @property
    def num_pages(self):
        if self.count == 0 and not self.allow_empty_first_page:
            return 0
        count = max(self.count - self.per_page + self.deltafirst, 0)
        hits = max(0, count - self.orphans)
        return 1 + ceil(hits / self.per_page)
于 2009-06-28T14:45:36.730 回答
1

object_list() 函数使用分页器来拆分列表。所以,如果你改变块的“大小”(7 对 8)......那么它会做你所看到的。

选择: 最后一个选择是靠不住的。不要那样做 :-) 要么“破解”它,要么转移到 Paginator。

破解它......在请求>第1页上,将一些额外的东西偷偷溜进row_list。我猜你可以通过list(row_list)强制它进入一个列表,并通过row_list.insert(0, None)在前面添加一个 None 或其他东西

分页...使用分页器

查看 + 模板...让您的视图只需将查询集 row_list 传递给模板。对第 1 页进行模板检查。您是否拥有 row_list 子集的循环/显示。在你的模板中有这样的逻辑是很糟糕的。它构成了一个复杂的模板。

于 2009-06-28T16:13:31.810 回答
0

我意识到这是一个老问题,但万一有人像我一样来到这里发现我的单元测试发现了一个问题。

亚历克斯基本上是正确的,但不要忘记也实施_get_num_pagesself.orphans + self.deltafirst否则最后一页将不正确。

def _get_num_pages(self):
    """Returns the total number of pages."""
    if self._num_pages is None:
        if self.count == 0 and not self.allow_empty_first_page:
            self._num_pages = 0
        else:
            hits = max(1, self.count - self.orphans + self.deltafirst)
            self._num_pages = int(ceil(hits / float(self.per_page)))
    return self._num_pages
num_pages = property(_get_num_pages)

和单元测试:

def test_ads_paginator(self):
    per_page = 10
    num_items = 100
    num_firstpage = 5
    expected_num_pages = 11

    items = range(num_items)
    paginator = AdsPaginator(items, per_page, deltafirst=per_page-num_firstpage)
    last_item = paginator.page(paginator.num_pages).object_list[-1]

    self.assertEqual(len(paginator.page(1)), num_firstpage)
    self.assertEqual(paginator.num_pages, expected_num_pages)
    self.assertEqual(last_item, items[-1])
于 2012-12-07T14:42:46.353 回答
0

对于我的特定场景,我希望在 1 个渲染模板中对对象进行分页(创建一个多页文档)。就我而言,我认为最简单的方法是忘记分页器并改用生成器。

    def pages_iter():
        page_num = 1
        num_records = lambda x: 30 if x > 1 else 10
        end_idx = 0

        while True:
            start_idx = end_idx
            end_idx += num_records(page_num)
            yield {
                'number': page_num,
                'object_list': donors[start_idx:end_idx]
            }

            if end_idx > donors.count() - 2:
                break
            page_num += 1

添加{ pages: page_iter }到您的页面上下文中,然后您就拥有了一个变量分页器。请注意,这num_records是一个接受 page_number 的函数,因此您确实拥有最大的灵活性。

在您的模板中,您可以像处理分页器一样处理它:

{% for page in pages %}
  {% if page.number == 1 %}
    {{ header }}
  {% endif %}

  {% for obj in page.object_list %}
    {{ obj }}
  {% endfor %}
{% endfor %}
于 2013-06-06T03:11:52.827 回答