Revert not finished 1000 limitation fix commit (ef7222d484).
authorPawel Solyga <Pawel.Solyga@gmail.com>
Fri, 15 May 2009 12:37:01 +0200
changeset 2312 71a5bc0f0398
parent 2311 e8262ca32109
child 2313 c39a81bce1bd
child 2314 0a0e603215d7
Revert not finished 1000 limitation fix commit (ef7222d484). We are going to put this into separate branch until it's finished.
app/soc/views/helper/lists.py
--- a/app/soc/views/helper/lists.py	Tue May 12 15:52:53 2009 +0200
+++ b/app/soc/views/helper/lists.py	Fri May 15 12:37:01 2009 +0200
@@ -22,6 +22,7 @@
   '"Pawel Solyga" <pawel.solyga@gmail.com>',
   ]
 
+import logging
 
 from soc.logic import dicts
 from soc.logic.models.user import logic as user_logic
@@ -60,8 +61,6 @@
 
 OFFSET_KEY = 'offset_%d'
 LIMIT_KEY = 'limit_%d'
-OFFSET_LINKID_KEY = 'offset_linkid_%d'
-REVERSE_DIRECTION_KEY = 'reverse_sort_direction_%d'
 
 
 def makeOffsetKey(limit_idx):
@@ -72,14 +71,6 @@
   return LIMIT_KEY % limit_idx
 
 
-def makeOffsetLinkidKey(limit_idx):
-  return OFFSET_LINKID_KEY % limit_idx
-
-
-def makeReverseDirectionKey(limit_idx):
-  return REVERSE_DIRECTION_KEY % limit_idx
-
-
 def getListParameters(request, list_index):
   """Retrieves, converts and validates values for one list
 
@@ -119,44 +110,30 @@
   else:
     limit = min(DEF_MAX_PAGINATION, limit)
 
-  result = dict(limit=limit, offset=offset)
-  offset_linkid = request.GET.get(makeOffsetLinkidKey(list_index),
-                                  '')
-  # TODO(dbentley): URL unescape
-  result['offset_linkid'] = offset_linkid
-
-  reverse_direction = makeReverseDirectionKey(list_index) in request.GET
-  result['reverse_direction'] = reverse_direction
-
-  return result
+  return dict(limit=limit, offset=offset)
 
 
-class LinkCreator(object):
-  """A way to create links for a page.
+def generateLinkFromGetArgs(request, offset_and_limits):
+  """Constructs the get args for the url.
   """
-  def __init__(self, request, list_idx, limit):
-    self.path = request.path
-    self.base_params = dict(
-        i for i in request.GET.iteritems() if
-        i[0].startswith('offset_') or i[0].startswith('limit_'))
-    self.idx = list_idx
-    self.base_params[makeLimitKey(self.idx)] = limit
+
+  args = ["%s=%s" % (k, v) for k, v in offset_and_limits.iteritems()]
+  link_suffix = '?' + '&'.join(args)
+
+  return request.path + link_suffix
+
 
-  def create(self, offset_linkid=None, export=False, reverse_direction=False):
-    params = self.base_params.copy()
-    if offset_linkid is not None:
-      # TODO(dbentley): URL encode
-      if offset_linkid == '':
-        try:
-          del params[makeOffsetLinkidKey(self.idx)]
-        except KeyError:
-          pass
-      else:
-        params[makeOffsetLinkidKey(self.idx)]=offset_linkid
-    if reverse_direction:
-      params[makeReverseDirectionKey(self.idx)]=True
-    link_suffix = '&'.join('%s=%s' % (k, v) for k, v in params.iteritems())
-    return '%s?%s' % (self.path, link_suffix)
+def generateLinkForRequest(request, base_params, updated_params):
+  """Create a link to the same page as request but with different params
+
+  Params:
+    request: the request for the page
+    base_params: the base parameters
+    updated_params: the parameters to update
+  """
+  params = base_params.copy()
+  params.update(updated_params)
+  return generateLinkFromGetArgs(request, params)
 
 
 def getListContent(request, params, filter=None, order=None,
@@ -197,36 +174,13 @@
   # as we only use this logic for getForFields, which is never overridden
   logic = params['logic']
 
-  limit_key = makeLimitKey(idx)
-  # offset_key = makeOffsetKey(idx)
-  # offset_linkid_key = makeOffsetLinkidKey(idx) 
-  # reverse_direction_key = makeReverseDirectionKey(idx)
+  limit_key, offset_key = makeLimitKey(idx), makeOffsetKey(idx)
 
   list_params = getListParameters(request, idx)
   limit, offset = list_params['limit'], list_params['offset']
-  offset_linkid = list_params['offset_linkid']
-  reverse_direction = list_params['reverse_direction']
   pagination_form = makePaginationForm(request, list_params['limit'],
                                        limit_key)
 
-  if offset_linkid:
-    if filter is None:
-      filter = {}
-
-    if reverse_direction:
-      filter['link_id <'] = offset_linkid
-    else:
-      filter['link_id >'] = offset_linkid
-
-    if order is None:
-      order = []
-    if reverse_direction:
-      order.append('-link_id')
-    else:
-      order.append('link_id')
-
-
-
   # Fetch one more to see if there should be a 'next' link
   data = logic.getForFields(filter=filter, limit=limit+1, offset=offset,
                             order=order)
@@ -235,61 +189,46 @@
     return None
 
   more = len(data) > limit
-  if reverse_direction:
-    data.reverse()
+
+  if more:
+    del data[limit:]
+
+  newest = next = prev = export_link = ''
+
+  base_params = dict(i for i in request.GET.iteritems() if
+                     i[0].startswith('offset_') or i[0].startswith('limit_'))
+
+  if params.get('list_key_order'):
+    export_link = generateLinkForRequest(request, base_params, {'export' : idx})
 
   if more:
-    if reverse_direction:
-      data = data[1:]
-    else:
-      data = data[:limit]
-
-  should_have_next_link = True
-  if not reverse_direction and not more:
-    should_have_next_link = False
+    # TODO(dbentley): here we need to implement a new field "last_key"
+    next = generateLinkForRequest(request, base_params, {offset_key : offset+limit,
+                                                         limit_key : limit})
 
-  # Calculating should_have_previous_link is tricky. It's possible we could
-  # be creating a previous link to a page that would have 0 entities.
-  # That would be suboptimal; what's a better way?
-  should_have_previous_link = False
-  if offset_linkid:
-    should_have_previous_link = True
-  if reverse_direction and not more:
-    should_have_previous_link = False
+  if offset > 0:
+    # TODO(dbentley): here we need to implement previous in the good way.
+    prev = generateLinkForRequest(request, base_params,
+                                  { offset_key : max(0, offset-limit),
+                                    limit_key : limit })
 
-  if data:
-    first_displayed_item = data[0]
-    last_displayed_item = data[-1]
-  else:
-    class Dummy(object):
-      pass
-    first_displayed_item = last_displayed_item = Dummy()
-    first_displayed_item.link_id = None
-  newest = next = prev = export_link = ''
-
-  link_creator = LinkCreator(request, idx, limit)
+  if offset > limit:
+    # Having a link to the first doesn't make sense on the first page (we're on
+    # it).  It also doesn't make sense on the second page (because the first
+    # page is the previous page).
 
-  if params.get('list_key_order'):
-    export_link = link_creator.create(export=True)
-
-  if should_have_next_link:
-    next = link_creator.create(offset_linkid=last_displayed_item.link_id)
-
-  if should_have_previous_link:
-    prev = link_creator.create(offset_linkid=first_displayed_item.link_id,
-                               reverse_direction=True)
-
-  newest = link_creator.create(offset_linkid='')
-
-  # TODO(dbentley): add a "last" link (which is now possible because we can
-  # query with a reverse linkid sorting
+    # NOTE(dbentley): I personally disagree that it's simpler to do that way,
+    # because sometimes you want to go to the first page without having to
+    # consider what page you're on now.
+    newest = generateLinkForGetArgs(request, base_params, {offset_key : 0,
+                                                           limit_key : limit})
 
   content = {
       'idx': idx,
       'data': data,
       'export': export_link,
-      'first': first_displayed_item.link_id,
-      'last': last_displayed_item.link_id,
+      'first': offset+1,
+      'last': len(data) > 1 and offset+len(data) or None,
       'logic': logic,
       'limit': limit,
       'newest': newest,