[Checkins] SVN: plone.z3cform/trunk/ Add batching to ``plone.z3cform.crud`` CrudForm.

Daniel Nouri daniel.nouri at gmail.com
Wed Aug 20 13:06:00 EDT 2008


Log message for revision 90030:
  Add batching to ``plone.z3cform.crud`` CrudForm.
  
  Thinking about moving crud out of plone.z3cform...
  

Changed:
  U   plone.z3cform/trunk/plone/z3cform/crud/README.txt
  A   plone.z3cform/trunk/plone/z3cform/crud/batch.pt
  A   plone.z3cform/trunk/plone/z3cform/crud/batch.txt
  U   plone.z3cform/trunk/plone/z3cform/crud/crud-table.pt
  U   plone.z3cform/trunk/plone/z3cform/crud/crud.py
  U   plone.z3cform/trunk/plone/z3cform/tests.py
  U   plone.z3cform/trunk/setup.py

-=-
Modified: plone.z3cform/trunk/plone/z3cform/crud/README.txt
===================================================================
--- plone.z3cform/trunk/plone/z3cform/crud/README.txt	2008-08-20 16:15:18 UTC (rev 90029)
+++ plone.z3cform/trunk/plone/z3cform/crud/README.txt	2008-08-20 17:05:58 UTC (rev 90030)
@@ -422,3 +422,37 @@
   False
   >>> 'Thomas' in storage
   True
+
+Using batching
+--------------
+
+The CrudForm base class supports batching.  When setting the
+``batch_size`` attribute to a value greater than ``0``, we'll only get
+as many items displayed per page.
+
+  >>> class MyBatchingForm(MyForm):
+  ...     batch_size = 2
+  >>> request = TestRequest()
+  >>> html = MyBatchingForm(None, request)()
+  >>> "Daniel" in html, "Maria" in html
+  (True, True)
+  >>> "THOMAS" in html
+  False
+
+  >>> request.form['crud-edit.form.page'] = '1'
+  >>> html = MyBatchingForm(None, request)()
+  >>> "Daniel" in html, "Maria" in html
+  (False, False)
+  >>> "THOMAS" in html
+  True
+
+Let's change Thomas' age on the second page:
+
+  >>> request.form['crud-edit.Thomas.widgets.name'] = u'Thomas'
+  >>> request.form['crud-edit.Thomas.widgets.age'] = 911
+  >>> request.form['crud-edit.form.buttons.edit'] = u'Apply changes'
+  >>> html = MyBatchingForm(None, request)()
+  >>> "Successfully updated" in html
+  True
+  >>> "911" in html
+  True

Added: plone.z3cform/trunk/plone/z3cform/crud/batch.pt
===================================================================
--- plone.z3cform/trunk/plone/z3cform/crud/batch.pt	                        (rev 0)
+++ plone.z3cform/trunk/plone/z3cform/crud/batch.pt	2008-08-20 17:05:58 UTC (rev 90030)
@@ -0,0 +1,9 @@
+<ul class="batch-navigation">
+  <li tal:repeat="page options/pages">
+    <a tal:content="page/label"
+       tal:attributes="href page/link"
+       tal:omit-tag="python:page['link'] is None">
+      Previous
+    </a>
+  </li>
+</ul>


Property changes on: plone.z3cform/trunk/plone/z3cform/crud/batch.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: plone.z3cform/trunk/plone/z3cform/crud/batch.txt
===================================================================
--- plone.z3cform/trunk/plone/z3cform/crud/batch.txt	                        (rev 0)
+++ plone.z3cform/trunk/plone/z3cform/crud/batch.txt	2008-08-20 17:05:58 UTC (rev 90030)
@@ -0,0 +1,67 @@
+Batching
+========
+
+The BatchNavigation adapter is for rendering batch navigation.
+
+  >>> from z3c.batching.batch import Batch
+  >>> from plone.z3cform.crud.crud import BatchNavigation
+
+Here's a little batch, set to three items per page and starting at the
+third item:
+
+  >>> l = [10, 11, 12, 20, 21, 22, 30, 31, 32, 40, 41, 42, 50, 51, 52]
+  >>> batch = Batch(l, start=3, size=3)
+  >>> list(batch)
+  [20, 21, 22]
+
+We can create the BatchNavigation now.  We set the make_link attribute
+to be a function that takes an argument (the page number) and returns
+a link to it:
+
+  >>> def make_link(page):
+  ...     return u"linkto?page=%s" % page
+
+  >>> from z3c.form.testing import TestRequest
+  >>> view = BatchNavigation(batch, TestRequest())
+  >>> view.make_link = make_link
+
+We monkey-patch the template to see what's being passed:
+
+  >>> from pprint import pprint
+  >>> def template(self, **kwargs):
+  ...     pprint(kwargs)
+  >>> BatchNavigation.template = template
+  >>> view()
+  {'batch': <Batch start=3, size=3>,
+   'pages': [{'link': u'linkto?page=0', 'label': u'Previous'},
+             {'link': u'linkto?page=0', 'label': u'1'},
+             {'link': None, 'label': u'2'},
+             {'link': u'linkto?page=2', 'label': u'3'},
+             {'link': u'linkto?page=3', 'label': u'4'},
+             {'link': u'linkto?page=4', 'label': u'5'},
+             {'link': u'linkto?page=2', 'label': u'Next'}]}
+
+Rendering for the first and last page, we can see that "Previous" and
+"Next" links are ommitted accordingly:
+
+  >>> batch = Batch(l, start=0, size=3)
+  >>> view.context = batch
+  >>> view()
+  {'batch': <Batch start=0, size=3>,
+   'pages': [{'link': None, 'label': u'1'},
+             {'link': u'linkto?page=1', 'label': u'2'},
+             {'link': u'linkto?page=2', 'label': u'3'},
+             {'link': u'linkto?page=3', 'label': u'4'},
+             {'link': u'linkto?page=4', 'label': u'5'},
+             {'link': u'linkto?page=1', 'label': u'Next'}]}
+
+  >>> batch = Batch(l, start=12, size=3)
+  >>> view.context = batch
+  >>> view()
+  {'batch': <Batch start=12, size=3>,
+   'pages': [{'link': u'linkto?page=3', 'label': u'Previous'},
+             {'link': u'linkto?page=0', 'label': u'1'},
+             {'link': u'linkto?page=1', 'label': u'2'},
+             {'link': u'linkto?page=2', 'label': u'3'},
+             {'link': u'linkto?page=3', 'label': u'4'},
+             {'link': None, 'label': u'5'}]}


Property changes on: plone.z3cform/trunk/plone/z3cform/crud/batch.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: plone.z3cform/trunk/plone/z3cform/crud/crud-table.pt
===================================================================
--- plone.z3cform/trunk/plone/z3cform/crud/crud-table.pt	2008-08-20 16:15:18 UTC (rev 90029)
+++ plone.z3cform/trunk/plone/z3cform/crud/crud-table.pt	2008-08-20 17:05:58 UTC (rev 90030)
@@ -15,6 +15,16 @@
 
   <form action="." method="post" tal:attributes="action request/getURL">
 
+    <ul tal:replace="structure view/render_batch_navigation">
+    </ul>
+    
+    <input type="hidden"
+           tal:define="batch view/batch"
+           tal:condition="python:batch.total &gt; 1"
+           tal:attributes="name python:'%spage' % view.prefix;
+                           value python:batch.number-1"
+           />
+
     <table class="crud-table" tal:define="rows view/subforms">
         <thead tal:define="row1 python:len(rows) and rows[0] or None"
                tal:condition="python:row1 is not None">

Modified: plone.z3cform/trunk/plone/z3cform/crud/crud.py
===================================================================
--- plone.z3cform/trunk/plone/z3cform/crud/crud.py	2008-08-20 16:15:18 UTC (rev 90029)
+++ plone.z3cform/trunk/plone/z3cform/crud/crud.py	2008-08-20 17:05:58 UTC (rev 90030)
@@ -1,3 +1,5 @@
+import sys
+
 from ZODB.POSException import ConflictError
 from zope import interface
 import zope.event
@@ -2,2 +4,3 @@
 import zope.lifecycleevent
+import zope.publisher.browser
 from z3c.form import button
@@ -8,7 +11,9 @@
 import z3c.form.widget
 from z3c.form.interfaces import DISPLAY_MODE, INPUT_MODE, NOVALUE
 from zope.app.pagetemplate import viewpagetemplatefile
+import z3c.batching.batch
 
+
 from plone.z3cform.widget import singlecheckboxwidget_factory
 from plone.z3cform import MessageFactory as _
 
@@ -28,6 +33,9 @@
 
     addform_factory = interface.Attribute("Factory used for the add form.")
 
+    batch_size = interface.Attribute(
+        "Set this to a value greater than 0 to display n items per page.")
+
     def get_items():
         """Subclasses must a list of all items to edit.
 
@@ -76,6 +84,7 @@
 
     update_schema = None
     view_schema = None
+    batch_size = 0
 
     @property
     def add_schema(self):
@@ -174,10 +183,42 @@
             freakList.append(item.field.title)
         return freakList
         
+class BatchItem(object):
+    def __init__(self, label, link=None):
+        self.label = label
+        self.link = link
+
+class BatchNavigation(zope.publisher.browser.BrowserView):
+    template = viewpagetemplatefile.ViewPageTemplateFile('batch.pt')
+
+    def make_link(self, page):
+        raise NotImplementedError()
+
+    def __call__(self):
+        pages = []
+        batch = self.context
+        if batch.total == 1:
+            return u""
+        else:
+            if batch.number > 1:
+                pages.append(dict(label=_("Previous"),
+                                  link=self.make_link(page=batch.number-2)))
+
+            for index in range(batch.total):
+                link = (index != batch.number-1 and
+                        self.make_link(page=index) or None)
+                pages.append(dict(label=unicode(index+1), link=link))
+
+            if batch.number < batch.total:
+                pages.append(dict(label=_("Next"),
+                                  link=self.make_link(page=batch.number)))
+
+            return self.template(batch=batch, pages=pages)
+
 class EditForm(form.Form):
     label = _(u"Edit")
     template = viewpagetemplatefile.ViewPageTemplateFile('crud-table.pt')
-        
+
     @property
     def prefix(self):
         parent_prefix = getattr(self.context, 'prefix', '')
@@ -189,13 +230,33 @@
     
     def _update_subforms(self):
         self.subforms = []
-        for id, item in self.context.get_items():
+        for id, item in self.batch:
             subform = EditSubForm(self, self.request)
             subform.content = item
             subform.content_id = id
             subform.update()
             self.subforms.append(subform)
 
+    @property
+    def batch(self):
+        items = self.context.get_items()
+        batch_size = self.context.batch_size or sys.maxint
+        page = self._page()
+        return z3c.batching.batch.Batch(
+            items, start=page*batch_size, size=batch_size)
+    #batch = zope.cachedescriptors.property.CachedProperty(batch)
+
+    def render_batch_navigation(self):
+        navigation = BatchNavigation(self.batch, self.request)
+        def make_link(page):
+            return "%s?%spage=%s" % (self.request.getURL(), self.prefix, page)
+        navigation.make_link = make_link
+        return navigation()
+
+    def _page(self):
+        name = '%spage' % self.prefix
+        return int(self.request.get(name, '0'))
+
     @button.buttonAndHandler(_('Apply changes'), name='edit')
     def handle_edit(self, action):
         success = _(u"Successfully updated")

Modified: plone.z3cform/trunk/plone/z3cform/tests.py
===================================================================
--- plone.z3cform/trunk/plone/z3cform/tests.py	2008-08-20 16:15:18 UTC (rev 90029)
+++ plone.z3cform/trunk/plone/z3cform/tests.py	2008-08-20 17:05:58 UTC (rev 90030)
@@ -74,6 +74,11 @@
            setUp=testing.setUp, tearDown=testing.tearDown,
            ),
 
+        doctest.DocFileSuite(
+           'crud/batch.txt',
+           setUp=testing.setUp, tearDown=testing.tearDown,
+           ),
+
         doctest.DocTestSuite(
            'plone.z3cform.crud.crud',
            setUp=testing.setUp, tearDown=testing.tearDown,

Modified: plone.z3cform/trunk/setup.py
===================================================================
--- plone.z3cform/trunk/setup.py	2008-08-20 16:15:18 UTC (rev 90029)
+++ plone.z3cform/trunk/setup.py	2008-08-20 17:05:58 UTC (rev 90030)
@@ -39,6 +39,7 @@
       install_requires=[
           'setuptools',
           'z3c.form',
+          'z3c.batching',
           'zope.i18n>=3.4',
           'zope.component',
       ],



More information about the Checkins mailing list