Commits

offline  committed 25463cb

every backend now have it's own settings

  • Participants
  • Parent commits 61d6b80

Comments (0)

Files changed (5)

File simplepagination/__init__.py

     http://bitbucket.org/offline/django-annoying/wiki/Home
     """
 
-    def __init__(self, key='object_list', style=None, per_page=10, 
-                frame_size=8, allow_user_per_page=False, fixed_user_per_page=None, 
-                template=None, anchor=None):
+    def __init__(self, key=None, style=None, per_page=None, 
+                frame_size=8, template=None, anchor=None):
         """
         Decorator parameters 
 
         frame_size - max pages numbers to show.
         """
 
-        self.key = key
-        self.style = style or getattr(settings, "PAGINATION_STYLE", "digg")
+        self.style = style or settings.PAGINATION_STYLE
+        self.anchor = anchor
         self.backend = get_instance_from_path(settings.PAGINATION_BACKENDS[self.style])
-        self.per_page = per_page
-        self.frame_size = frame_size
-        self.allow_user_per_page = allow_user_per_page
-        self.template = template or 'paginator_%s.html' % style
-        self.fixed_user_per_page = fixed_user_per_page
-        self.anchor = anchor
+        self.key = key or self.backend.KEY
+        self.per_page = per_page or self.backend.PER_PAGE
+        self.frame_size = frame_size or self.backend.FRAME_SIZE
+        self.template = template or self.backend.TEMPLATE or 'paginator_%s.html' % style
+        self.user_per_page_allowed = self.backend.USER_PER_PAGE_ALLOWED
+        self.user_per_page_max = self.backend.USER_PER_PAGE_MAX
         
     def __call__(self, function):
         """
         except (ValueError, KeyError):
             page_num = 1
         
-        per_page = self.per_page
-        if self.allow_user_per_page and 'per_page' in params:
+        # we dont modify self.per_page because it's decorator
+        # and it initialize only once.
+        per_page = self.per_page 
+
+        # per_page should change from GET parameters only if this
+        # is allowed in settings or backend, also it must be lower
+        # or equal then self.user_per_page_max.
+        if self.user_per_page_allowed and 'per_page' in params:
             try:
                 user_per_page = int(params['per_page'])
-                if not self.fixed_user_per_page or user_per_page not in self.fixed_user_per_page:
+                if user_per_page <= self.user_per_page_max:
                     per_page = user_per_page
+                else:
+                    per_page = self.user_per_page_max
+                    params['per_page'] = self.user_per_page_max
             except (ValueError, KeyError):
                 params['per_page'] = self.per_page
+
         elif 'per_page' in params:
             params.pop('per_page')
         
+        # we will paginate value of self.key, original object will be replaced 
+        # by items that should be only in current page.
         try:
             paginate_qs = output.pop(self.key)
         except KeyError:
             raise KeyError("Key '%s' not found in view's returned dictionary" % self.key)
+
+        # create django built in paginator object
         paginator = Paginator(paginate_qs, per_page)
         
         try:
+            # check that asked page is exists
             page = paginator.page(page_num)
         except EmptyPage:
             raise Http404()
+
+        # replace paginated items by only items we should see.
+        output[self.key] = page.object_list
         
+        # extra data that we may need to build links
         data = {}
         data['page_num'] = page_num # active page number
         data['per_page'] = per_page # items per page
         data['anchor'] = self.anchor # ancor
         data['pages'] = pages = paginator.num_pages # number of pages
         data['paginator_template'] = self.template
-        data['allow_user_per_page'] = self.allow_user_per_page
 
-        output[self.key] = page.object_list
+        # execute the pagination function
         data.update(self.backend.paginate(self.frame_size, pages, page_num))
+
+        # your view now have extra key 'paginator' with all extra data inside.
         output['paginator'] = data
         
         return output

File simplepagination/backends/__init__.py

+from simplepagination import settings 
+
+
+class Paginator(object):
+    def paginate(self, frame_size, number_of_pages, current_page):
+        raise NotImplemented
+
+    # see settings file for explanations
+
+    KEY = getattr(settings, 'PAGINATION_KEY')
+    PER_PAGE = getattr(settings, 'PAGINATION_PER_PAGE')
+    FRAME_SIZE = getattr(settings, 'PAGINATION_FRAME_SIZE')
+    TEMPLATE = getattr(settings, 'PAGINATOR_TEMPLATE')
+    USER_PER_PAGE_ALLOWED = getattr(settings, 'PAGINATION_USER_PER_PAGE_ALLOWED')
+    USER_PER_PAGE_MAX = getattr(settings, 'PAGINATION_USER_PER_PAGE_MAX')

File simplepagination/backends/digg.py

-class DiggPaginator(object):
+from simplepagination.backends import Paginator
 
-    def paginate(self, frame_size, pages, page_num):
+
+class DiggPaginator(Paginator):
+
+    def paginate(self, frame_size, number_of_pages, current_page):
         output = {}
-        if page_num > 1:
-            output['PREVIOUS'] = page_num -1
-        if page_num < pages:
-            output['NEXT'] = page_num + 1
-        if pages > frame_size and pages <= frame_size +2:
-            output['left_page_numbers'] = range(1, pages + 1)
-        elif pages <= frame_size:
-            output['left_page_numbers'] = range(1, pages + 1)
-        elif pages > frame_size and page_num < frame_size - 1:
+        if current_page > 1:
+            output['PREVIOUS'] = current_page -1
+        if current_page < number_of_pages:
+            output['NEXT'] = current_page + 1
+        if number_of_pages > frame_size and number_of_pages <= frame_size +2:
+            output['left_page_numbers'] = range(1, number_of_pages + 1)
+        elif number_of_pages <= frame_size:
+            output['left_page_numbers'] = range(1, number_of_pages + 1)
+        elif number_of_pages > frame_size and current_page < frame_size - 1:
             output['left_page_numbers'] = range(1, frame_size + 1)
-            output['right_page_numbers'] = range(pages -1, pages +1)
-        elif pages > frame_size and page_num > frame_size - 2 and pages - (frame_size / 2) <= page_num + 1:
+            output['right_page_numbers'] = range(number_of_pages -1, number_of_pages +1)
+        elif number_of_pages > frame_size and current_page > frame_size - 2 and number_of_pages - (frame_size / 2) <= current_page + 1:
             output['left_page_numbers'] = range(1, 3)
-            output['middle_page_numbers'] = range(pages - frame_size + 1, pages +1)
-        elif pages > frame_size and page_num > frame_size - 2:
+            output['middle_page_numbers'] = range(number_of_pages - frame_size + 1, number_of_pages +1)
+        elif number_of_pages > frame_size and current_page > frame_size - 2:
             output['left_page_numbers'] = range(1, 3)
-            output['middle_page_numbers'] = range(page_num - (frame_size / 2) +1, page_num + (frame_size / 2))
-            output['right_page_numbers'] = range(pages -1, pages +1)
+            output['middle_page_numbers'] = range(current_page - (frame_size / 2) +1, current_page + (frame_size / 2))
+            output['right_page_numbers'] = range(number_of_pages -1, number_of_pages +1)
         return output
 

File simplepagination/backends/filmfeed.py

-class FilmfeedPaginator(object):
-    def paginate(self, frame_size, pages, page_num):
+from simplepagination.backends import Paginator
+
+
+class FilmfeedPaginator(Paginator):
+    def paginate(self, frame_size, number_of_pages, current_page):
         output = {}
-        if pages < frame_size:
-            output['page_numbers'] = range(1, pages + 1)
-        elif page_num < (frame_size / 2) + 1:
+        if number_of_pages < frame_size:
+            output['page_numbers'] = range(1, number_of_pages + 1)
+        elif current_page < (frame_size / 2) + 1:
             output['page_numbers'] = range(1, frame_size + 1)
-        elif page_num >= (frame_size / 2) + 1 and pages - (frame_size / 2) <= page_num:
-            output['page_numbers'] = range(pages - frame_size + 1, pages + 1)
-        elif page_num >= (frame_size / 2) + 1:
-            start = page_num - (frame_size / 2)
-            end = page_num + (frame_size / 2)
+        elif current_page >= (frame_size / 2) + 1 and number_of_pages - (frame_size / 2) <= current_page:
+            output['page_numbers'] = range(number_of_pages - frame_size + 1, number_of_pages + 1)
+        elif current_page >= (frame_size / 2) + 1:
+            start = current_page - (frame_size / 2)
+            end = current_page + (frame_size / 2)
             output['page_numbers'] = range(start, end + 1)
         return output
 

File simplepagination/settings.py

 from django.conf import settings
 
+### BACKENDS #################################################################################################
+# Dictionary with paginator name as key and path to class as value.                                          #
+# Class must have 'paginate' function inside that receive 3 parameters                                       #
+# frame_size, number_of_pages and current_page_number                                                        #
+# this function must return dictionary that will be added to view dictionary under key 'paginator'           #
+PAGINATION_BACKENDS = getattr(settings, 'PAGINATION_BACKENDS', {                                             #
+    'digg': 'simplepagination.backends.digg.DiggPaginator',                                                  #
+    'filmfeed': 'simplepagination.backends.filmfeed.FilmfeedPaginator',                                      #
+})                                                                                                           #
+##############################################################################################################
 
-PAGINATION_BACKENDS = getattr(settings, 'PAGINATION_BACKENDS', {
-    'digg': 'simplepagination.backends.digg.DiggPaginator',
-    'filmfeed': 'simplepagination.backends.filmfeed.FilmfeedPaginator',
-})
+### STYLE ####################################################################################################
+# Style is name of the backend, it will be used as default style for all paginators if no style parameter    #
+# is passed to decorator.                                                                                    #
+PAGINATION_STYLE = getattr(settings, 'PAGINATION_STYLE', 'digg')                                             #
+##############################################################################################################
 
-PAGINATION_STYLE = getattr(settings, 'PAGINATION_STYLE', 'digg')
+### KEY ######################################################################################################
+# Key is name of the key with items in view returned dictionary that we paginate                             #
+PAGINATION_KEY = getattr(settings, 'PAGINATION_KEY', 'object_list')                                          #
+##############################################################################################################
+
+### PER_PAGE #################################################################################################
+# Default number of items on page                                                                            #
+PAGINATION_PER_PAGE = getattr(settings, 'PAGINATION_PER_PAGE', 10)                                           #
+##############################################################################################################
+
+### FRAME_SIZE ###############################################################################################
+# Default frame size of paginator.                                                                           #
+PAGINATION_FRAME_SIZE = getattr(settings, 'PAGINATION_FRAME_SIZE', 8)                                        #
+##############################################################################################################
+
+### USER_PER_PAGE_ALLOWED ####################################################################################
+# IF set to True, user can manualy change per_page setting with GET parameters, the default is to allow      #
+# it in debug mode and disable in production.                                                                #
+PAGINATION_USER_PER_PAGE_ALLOWED = getattr(settings, 'PAGINATION_USER_PER_PAGE_ALLOWED', settings.DEBUG)     #
+##############################################################################################################
+
+### USER_PER_PAGE_MAX ########################################################################################
+# Maximum items per page                                                                                     #
+PAGINATION_USER_PER_PAGE_MAX = getattr(settings, 'PAGINATION_USER_PER_PAGE_MAX', 100)                        #
+##############################################################################################################
+
+### TEMPLATE #################################################################################################
+# Default template for all paginators, dont set it if you use more than one backends                         #
+PAGINATOR_TEMPLATE = getattr(settings, 'PAGINATOR_TEMPLATE', None)                                           #
+##############################################################################################################