Made the Paginator class a bit more backwards compatible with the lecacy `ObjectPaginator` class by using the `ObjectPaginator`'s `_get_count` method. Instead of explicitly checking for an instance of `QuerySet`, this now allows any object with a `count()` or `__len__()` method defined to be passed to Paginator. For one, this is useful when you have custom `QuerySet`-like classes that implement a `count()` method but don't inherit from `QuerySet` explicitly.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@8121 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
6a287ed946
commit
9a5301ccbc
|
@ -42,10 +42,12 @@ class Paginator(object):
|
||||||
def _get_count(self):
|
def _get_count(self):
|
||||||
"Returns the total number of objects, across all pages."
|
"Returns the total number of objects, across all pages."
|
||||||
if self._count is None:
|
if self._count is None:
|
||||||
from django.db.models.query import QuerySet
|
try:
|
||||||
if isinstance(self.object_list, QuerySet):
|
|
||||||
self._count = self.object_list.count()
|
self._count = self.object_list.count()
|
||||||
else:
|
except (AttributeError, TypeError):
|
||||||
|
# AttributeError if object_list has no count() method.
|
||||||
|
# TypeError if object_list.count() requires arguments
|
||||||
|
# (i.e. is of type list).
|
||||||
self._count = len(self.object_list)
|
self._count = len(self.object_list)
|
||||||
return self._count
|
return self._count
|
||||||
count = property(_get_count)
|
count = property(_get_count)
|
||||||
|
@ -169,22 +171,8 @@ class ObjectPaginator(Paginator):
|
||||||
return self.count
|
return self.count
|
||||||
return page_number * self.num_per_page
|
return page_number * self.num_per_page
|
||||||
|
|
||||||
def _get_count(self):
|
|
||||||
# The old API allowed for self.object_list to be either a QuerySet or a
|
|
||||||
# list. Here, we handle both.
|
|
||||||
if self._count is None:
|
|
||||||
try:
|
|
||||||
self._count = self.object_list.count()
|
|
||||||
except (AttributeError, TypeError):
|
|
||||||
# AttributeError if object_list has no count() method.
|
|
||||||
# TypeError if object_list.count() requires arguments
|
|
||||||
# (i.e. is of type list).
|
|
||||||
self._count = len(self.object_list)
|
|
||||||
return self._count
|
|
||||||
count = property(_get_count)
|
|
||||||
|
|
||||||
# The old API called it "hits" instead of "count".
|
# The old API called it "hits" instead of "count".
|
||||||
hits = count
|
hits = Paginator.count
|
||||||
|
|
||||||
# The old API called it "pages" instead of "num_pages".
|
# The old API called it "pages" instead of "num_pages".
|
||||||
pages = Paginator.num_pages
|
pages = Paginator.num_pages
|
||||||
|
|
|
@ -59,10 +59,12 @@ page::
|
||||||
...
|
...
|
||||||
InvalidPage
|
InvalidPage
|
||||||
|
|
||||||
Note that you can give ``Paginator`` a list/tuple or a Django ``QuerySet``. The
|
Note that you can give ``Paginator`` a list/tuple, a Django ``QuerySet``, or
|
||||||
only difference is in implementation; if you pass a ``QuerySet``, the
|
any other object with a ``count()`` or ``__len__()`` method. When determining
|
||||||
``Paginator`` will call its ``count()`` method instead of using ``len()``,
|
the number of objects contained in the passed object, ``Paginator`` will first
|
||||||
because the former is more efficient.
|
try calling ``count()``, then fallback to using ``len()`` if the passed object
|
||||||
|
has no ``count()`` method. This allows objects such as Django's ``QuerySet`` to
|
||||||
|
use a more efficient ``count()`` method when available.
|
||||||
|
|
||||||
``Paginator`` objects
|
``Paginator`` objects
|
||||||
=====================
|
=====================
|
||||||
|
|
|
@ -140,6 +140,31 @@ True
|
||||||
>>> p.end_index()
|
>>> p.end_index()
|
||||||
5
|
5
|
||||||
|
|
||||||
|
# Paginator can be passed other objects with a count() method.
|
||||||
|
>>> class CountContainer:
|
||||||
|
... def count(self):
|
||||||
|
... return 42
|
||||||
|
>>> paginator = Paginator(CountContainer(), 10)
|
||||||
|
>>> paginator.count
|
||||||
|
42
|
||||||
|
>>> paginator.num_pages
|
||||||
|
5
|
||||||
|
>>> paginator.page_range
|
||||||
|
[1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
# Paginator can be passed other objects that implement __len__.
|
||||||
|
>>> class LenContainer:
|
||||||
|
... def __len__(self):
|
||||||
|
... return 42
|
||||||
|
>>> paginator = Paginator(LenContainer(), 10)
|
||||||
|
>>> paginator.count
|
||||||
|
42
|
||||||
|
>>> paginator.num_pages
|
||||||
|
5
|
||||||
|
>>> paginator.page_range
|
||||||
|
[1, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
|
||||||
################################
|
################################
|
||||||
# Legacy API (ObjectPaginator) #
|
# Legacy API (ObjectPaginator) #
|
||||||
################################
|
################################
|
||||||
|
|
Loading…
Reference in New Issue