django-pagination-1.0.7/000755 000765 000024 00000000000 11370430554 015350 5ustar00brianstaff000000 000000 django-pagination-1.0.7/CONTRIBUTORS.txt000644 000765 000024 00000000145 11360733377 020056 0ustar00brianstaff000000 000000 Eric Florenzano Martin Mahner James Tauber django-pagination-1.0.7/django_pagination.egg-info/000755 000765 000024 00000000000 11370430554 022515 5ustar00brianstaff000000 000000 django-pagination-1.0.7/docs/000755 000765 000024 00000000000 11370430554 016300 5ustar00brianstaff000000 000000 django-pagination-1.0.7/LICENSE.txt000644 000765 000024 00000002761 11360733377 017211 0ustar00brianstaff000000 000000 Copyright (c) 2008, Eric Florenzano All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the author nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. django-pagination-1.0.7/MANIFEST.in000644 000765 000024 00000000176 11360733377 017122 0ustar00brianstaff000000 000000 include LICENSE.txt include CONTRIBUTORS.txt recursive-include docs * recursive-include pagination/templates/pagination *.htmldjango-pagination-1.0.7/pagination/000755 000765 000024 00000000000 11370430554 017501 5ustar00brianstaff000000 000000 django-pagination-1.0.7/PKG-INFO000644 000765 000024 00000011053 11370430554 016445 0ustar00brianstaff000000 000000 Metadata-Version: 1.0 Name: django-pagination Version: 1.0.7 Summary: django-pagination Home-page: http://django-pagination.googlecode.com/ Author: Eric Florenzano Author-email: floguy@gmail.com License: BSD Description: How to use django-pagination ---------------------------- ``django-pagination`` allows for easy Digg-style pagination without modifying your views. There are really 5 steps to setting it up with your projects (not including installation, which is covered in INSTALL.txt in this same directory.) 1. List this application in the ``INSTALLED_APPS`` portion of your settings file. Your settings file might look something like:: INSTALLED_APPS = ( # ... 'pagination', ) 2. Install the pagination middleware. Your settings file might look something like:: MIDDLEWARE_CLASSES = ( # ... 'pagination.middleware.PaginationMiddleware', ) 3. If it's not already added in your setup, add the request context processor. Note that context processors are set by default implicitly, so to set them explicitly, you need to copy and paste this code into your under the value TEMPLATE_CONTEXT_PROCESSORS:: ("django.core.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", "django.core.context_processors.request") 4. Add this line at the top of your template to load the pagination tags: {% load pagination_tags %} 5. Decide on a variable that you would like to paginate, and use the autopaginate tag on that variable before iterating over it. This could take one of two forms (using the canonical ``object_list`` as an example variable): {% autopaginate object_list %} This assumes that you would like to have the default 20 results per page. If you would like to specify your own amount of results per page, you can specify that like so: {% autopaginate object_list 10 %} Note that this replaces ``object_list`` with the list for the current page, so you can iterate over the ``object_list`` like you normally would. 6. Now you want to display the current page and the available pages, so somewhere after having used autopaginate, use the paginate inclusion tag: {% paginate %} This does not take any arguments, but does assume that you have already called autopaginate, so make sure to do so first. That's it! You have now paginated ``object_list`` and given users of the site a way to navigate between the different pages--all without touching your views. Optional Settings ------------------ In django-pagination, there are no required settings. There are, however, a small set of optional settings useful for changing the default behavior of the pagination tags. Here's an overview: ``PAGINATION_DEFAULT_PAGINATION`` The default amount of items to show on a page if no number is specified. ``PAGINATION_DEFAULT_WINDOW`` The number of items to the left and to the right of the current page to display (accounting for ellipses). ``PAGINATION_DEFAULT_ORPHANS`` The number of orphans allowed. According to the Django documentation, orphans are defined as:: The minimum number of items allowed on the last page, defaults to zero. ``PAGINATION_INVALID_PAGE_RAISES_404`` Determines whether an invalid page raises an ``Http404`` or just sets the ``invalid_page`` context variable. ``True`` does the former and ``False`` does the latter. Keywords: pagination,django Platform: UNKNOWN Classifier: Programming Language :: Python Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Framework :: Django Classifier: Environment :: Web Environment django-pagination-1.0.7/setup.cfg000644 000765 000024 00000000073 11370430554 017171 0ustar00brianstaff000000 000000 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 django-pagination-1.0.7/._setup.py000644 000765 000024 00000000272 11370430526 017277 0ustar00brianstaff000000 000000 Mac OS X  2ˆºATTR‰bẘ"˜"com.macromates.caret{ column = 17; line = 2; }django-pagination-1.0.7/setup.py000644 000765 000024 00000010014 11370430526 017055 0ustar00brianstaff000000 000000 from setuptools import setup, find_packages version = '1.0.7' LONG_DESCRIPTION = """ How to use django-pagination ---------------------------- ``django-pagination`` allows for easy Digg-style pagination without modifying your views. There are really 5 steps to setting it up with your projects (not including installation, which is covered in INSTALL.txt in this same directory.) 1. List this application in the ``INSTALLED_APPS`` portion of your settings file. Your settings file might look something like:: INSTALLED_APPS = ( # ... 'pagination', ) 2. Install the pagination middleware. Your settings file might look something like:: MIDDLEWARE_CLASSES = ( # ... 'pagination.middleware.PaginationMiddleware', ) 3. If it's not already added in your setup, add the request context processor. Note that context processors are set by default implicitly, so to set them explicitly, you need to copy and paste this code into your under the value TEMPLATE_CONTEXT_PROCESSORS:: ("django.core.context_processors.auth", "django.core.context_processors.debug", "django.core.context_processors.i18n", "django.core.context_processors.media", "django.core.context_processors.request") 4. Add this line at the top of your template to load the pagination tags: {% load pagination_tags %} 5. Decide on a variable that you would like to paginate, and use the autopaginate tag on that variable before iterating over it. This could take one of two forms (using the canonical ``object_list`` as an example variable): {% autopaginate object_list %} This assumes that you would like to have the default 20 results per page. If you would like to specify your own amount of results per page, you can specify that like so: {% autopaginate object_list 10 %} Note that this replaces ``object_list`` with the list for the current page, so you can iterate over the ``object_list`` like you normally would. 6. Now you want to display the current page and the available pages, so somewhere after having used autopaginate, use the paginate inclusion tag: {% paginate %} This does not take any arguments, but does assume that you have already called autopaginate, so make sure to do so first. That's it! You have now paginated ``object_list`` and given users of the site a way to navigate between the different pages--all without touching your views. Optional Settings ------------------ In django-pagination, there are no required settings. There are, however, a small set of optional settings useful for changing the default behavior of the pagination tags. Here's an overview: ``PAGINATION_DEFAULT_PAGINATION`` The default amount of items to show on a page if no number is specified. ``PAGINATION_DEFAULT_WINDOW`` The number of items to the left and to the right of the current page to display (accounting for ellipses). ``PAGINATION_DEFAULT_ORPHANS`` The number of orphans allowed. According to the Django documentation, orphans are defined as:: The minimum number of items allowed on the last page, defaults to zero. ``PAGINATION_INVALID_PAGE_RAISES_404`` Determines whether an invalid page raises an ``Http404`` or just sets the ``invalid_page`` context variable. ``True`` does the former and ``False`` does the latter. """ setup( name='django-pagination', version=version, description="django-pagination", long_description=LONG_DESCRIPTION, classifiers=[ "Programming Language :: Python", "Topic :: Software Development :: Libraries :: Python Modules", "Framework :: Django", "Environment :: Web Environment", ], keywords='pagination,django', author='Eric Florenzano', author_email='floguy@gmail.com', url='http://django-pagination.googlecode.com/', license='BSD', packages=find_packages(), include_package_data=True, zip_safe=False, ) django-pagination-1.0.7/pagination/__init__.py000644 000765 000024 00000000001 11360733377 021611 0ustar00brianstaff000000 000000 django-pagination-1.0.7/pagination/middleware.py000644 000765 000024 00000001064 11360733377 022201 0ustar00brianstaff000000 000000 def get_page(self): """ A function which will be monkeypatched onto the request to get the current integer representing the current page. """ try: return int(self.REQUEST['page']) except (KeyError, ValueError, TypeError): return 1 class PaginationMiddleware(object): """ Inserts a variable representing the current page onto the request object if it exists in either **GET** or **POST** portions of the request. """ def process_request(self, request): request.__class__.page = property(get_page)django-pagination-1.0.7/pagination/models.py000644 000765 000024 00000000001 11360733377 021335 0ustar00brianstaff000000 000000 django-pagination-1.0.7/pagination/paginator.py000644 000765 000024 00000013213 11360733377 022047 0ustar00brianstaff000000 000000 from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage class InfinitePaginator(Paginator): """ Paginator designed for cases when it's not important to know how many total pages. This is useful for any object_list that has no count() method or can be used to improve performance for MySQL by removing counts. The orphans parameter has been removed for simplicity and there's a link template string for creating the links to the next and previous pages. """ def __init__(self, object_list, per_page, allow_empty_first_page=True, link_template='/page/%d/'): orphans = 0 # no orphans super(InfinitePaginator, self).__init__(object_list, per_page, orphans, allow_empty_first_page) # no count or num pages del self._num_pages, self._count # bonus links self.link_template = link_template def validate_number(self, number): """ Validates the given 1-based page number. """ try: number = int(number) except ValueError: raise PageNotAnInteger('That page number is not an integer') if number < 1: raise EmptyPage('That page number is less than 1') return number def page(self, number): """ Returns a Page object for the given 1-based page number. """ number = self.validate_number(number) bottom = (number - 1) * self.per_page top = bottom + self.per_page page_items = self.object_list[bottom:top] # check moved from validate_number if not page_items: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return InfinitePage(page_items, number, self) def _get_count(self): """ Returns the total number of objects, across all pages. """ raise NotImplementedError count = property(_get_count) def _get_num_pages(self): """ Returns the total number of pages. """ raise NotImplementedError num_pages = property(_get_num_pages) def _get_page_range(self): """ Returns a 1-based range of pages for iterating through within a template for loop. """ raise NotImplementedError page_range = property(_get_page_range) class InfinitePage(Page): def __repr__(self): return '' % self.number def has_next(self): """ Checks for one more item than last on this page. """ try: next_item = self.paginator.object_list[ self.number * self.paginator.per_page] except IndexError: return False return True def end_index(self): """ Returns the 1-based index of the last object on this page, relative to total objects found (hits). """ return ((self.number - 1) * self.paginator.per_page + len(self.object_list)) #Bonus methods for creating links def next_link(self): if self.has_next(): return self.paginator.link_template % (self.number + 1) return None def previous_link(self): if self.has_previous(): return self.paginator.link_template % (self.number - 1) return None class FinitePaginator(InfinitePaginator): """ Paginator for cases when the list of items is already finite. A good example is a list generated from an API call. This is a subclass of InfinitePaginator because we have no idea how many items exist in the full collection. To accurately determine if the next page exists, a FinitePaginator MUST be created with an object_list_plus that may contain more items than the per_page count. Typically, you'll have an object_list_plus with one extra item (if there's a next page). You'll also need to supply the offset from the full collection in order to get the page start_index. This is a very silly class but useful if you love the Django pagination conventions. """ def __init__(self, object_list_plus, per_page, offset=None, allow_empty_first_page=True, link_template='/page/%d/'): super(FinitePaginator, self).__init__(object_list_plus, per_page, allow_empty_first_page, link_template) self.offset = offset def validate_number(self, number): super(FinitePaginator, self).validate_number(number) # check for an empty list to see if the page exists if not self.object_list: if number == 1 and self.allow_empty_first_page: pass else: raise EmptyPage('That page contains no results') return number def page(self, number): """ Returns a Page object for the given 1-based page number. """ number = self.validate_number(number) # remove the extra item(s) when creating the page page_items = self.object_list[:self.per_page] return FinitePage(page_items, number, self) class FinitePage(InfinitePage): def has_next(self): """ Checks for one more item than last on this page. """ try: next_item = self.paginator.object_list[self.paginator.per_page] except IndexError: return False return True def start_index(self): """ Returns the 1-based index of the first object on this page, relative to total objects in the paginator. """ ## TODO should this holler if you haven't defined the offset? return self.paginator.offsetdjango-pagination-1.0.7/pagination/templates/000755 000765 000024 00000000000 11370430554 021477 5ustar00brianstaff000000 000000 django-pagination-1.0.7/pagination/templatetags/000755 000765 000024 00000000000 11370430554 022173 5ustar00brianstaff000000 000000 django-pagination-1.0.7/pagination/tests.py000644 000765 000024 00000010123 11360733430 021210 0ustar00brianstaff000000 000000 """ >>> from django.core.paginator import Paginator >>> from pagination.templatetags.pagination_tags import paginate >>> from django.template import Template, Context >>> p = Paginator(range(15), 2) >>> pg = paginate({'paginator': p, 'page_obj': p.page(1)}) >>> pg['pages'] [1, 2, 3, 4, 5, 6, 7, 8] >>> pg['records']['first'] 1 >>> pg['records']['last'] 2 >>> p = Paginator(range(15), 2) >>> pg = paginate({'paginator': p, 'page_obj': p.page(8)}) >>> pg['pages'] [1, 2, 3, 4, 5, 6, 7, 8] >>> pg['records']['first'] 15 >>> pg['records']['last'] 15 >>> p = Paginator(range(17), 2) >>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] [1, 2, 3, 4, 5, 6, 7, 8, 9] >>> p = Paginator(range(19), 2) >>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] [1, 2, 3, 4, None, 7, 8, 9, 10] >>> p = Paginator(range(21), 2) >>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] [1, 2, 3, 4, None, 8, 9, 10, 11] # Testing orphans >>> p = Paginator(range(5), 2, 1) >>> paginate({'paginator': p, 'page_obj': p.page(1)})['pages'] [1, 2] >>> p = Paginator(range(21), 2, 1) >>> pg = paginate({'paginator': p, 'page_obj': p.page(1)}) >>> pg['pages'] [1, 2, 3, 4, None, 7, 8, 9, 10] >>> pg['records']['first'] 1 >>> pg['records']['last'] 2 >>> p = Paginator(range(21), 2, 1) >>> pg = paginate({'paginator': p, 'page_obj': p.page(10)}) >>> pg['pages'] [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> pg['records']['first'] 19 >>> pg['records']['last'] 21 >>> t = Template("{% load pagination_tags %}{% autopaginate var 2 %}{% paginate %}") >>> from django.http import HttpRequest as DjangoHttpRequest >>> class HttpRequest(DjangoHttpRequest): ... page = 1 >>> t.render(Context({'var': range(21), 'request': HttpRequest()})) u'\\n\\n