[Checkins] SVN: zope3org/trunk/src/zorg/multiform/ handle batch and
sort of subforms
Stefan Martin
s.martin at iwm-kmrc.de
Tue Apr 11 10:39:58 EDT 2006
Log message for revision 66854:
handle batch and sort of subforms
Changed:
U zope3org/trunk/src/zorg/multiform/configure.zcml
U zope3org/trunk/src/zorg/multiform/gridform.py
U zope3org/trunk/src/zorg/multiform/gridform.txt
U zope3org/trunk/src/zorg/multiform/interfaces.py
U zope3org/trunk/src/zorg/multiform/multiform.py
U zope3org/trunk/src/zorg/multiform/tests.py
-=-
Modified: zope3org/trunk/src/zorg/multiform/configure.zcml
===================================================================
--- zope3org/trunk/src/zorg/multiform/configure.zcml 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/configure.zcml 2006-04-11 14:39:57 UTC (rev 66854)
@@ -15,6 +15,12 @@
factory=".selection.FormLocationSelection"
/>
+ <adapter for="zope.interface.Interface
+ zope.schema.interfaces.IField"
+ factory=".sort.SchemaSorter"
+ provides=".interfaces.ISorter"
+ />
+
<!-- namedtemplate for IParentAction -->
<adapter factory=".multiform.render_submit_button" name="render" />
Modified: zope3org/trunk/src/zorg/multiform/gridform.py
===================================================================
--- zope3org/trunk/src/zorg/multiform/gridform.py 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/gridform.py 2006-04-11 14:39:57 UTC (rev 66854)
@@ -1,10 +1,13 @@
-from interfaces import IGridForm,IGridItemForm
+
+from zope.component import getMultiAdapter
+from zope.formlib import namedtemplate
from zope.interface import implements
-import multiform
-from zope.formlib import namedtemplate
from zope.app.pagetemplate import ViewPageTemplateFile
+from interfaces import IGridForm, IGridItemForm, ISorter
+import multiform
+
default_grid_template = namedtemplate.NamedTemplateImplementation(
ViewPageTemplateFile('grid.pt'), IGridForm)
@@ -17,5 +20,114 @@
template = namedtemplate.NamedTemplate('default')
class GridFormBase(multiform.MultiFormBase):
+
implements(IGridForm)
+
template = namedtemplate.NamedTemplate('default')
+
+ def __init__(self, context, request):
+ context = FilterMapping(context, request, self)
+ super(GridFormBase,self).__init__(context, request)
+
+
+class FilterMapping(object):
+
+ def __init__(self, context, request, form):
+ self.context = context
+ self.request = request
+ self.form = form
+ self.batch_start = request.form.get(
+ '%s.handle.batch_start' % form.prefix, None)
+ self.batch_size = request.form.get(
+ '%s.handle.batch_size' % form.prefix, None)
+ self.sort_on = request.form.get(
+ '%s.handle.sort_on' % form.prefix, None)
+ self.sort_reverse = request.form.get(
+ '%s.handle.sort_reverse' % form.prefix, None)
+
+ def sortAllKeys(self):
+ sorter = None
+ if self.sort_on:
+ sortName = self.sort_on
+ sortField = None
+ for field in self.form.itemFormFactory.form_fields:
+ if field.__name__ == sortName:
+ sortField = field
+ break
+ if sortField:
+ sorter = getMultiAdapter((sortField.field.interface,
+ sortField.field),ISorter)
+ if sorter:
+ items = sorter.sort(self.context.items())
+ if self.sort_reverse:
+ items.reverse()
+ keys = []
+ for key, value in items:
+ yield key
+ else:
+ for key in self.context.keys():
+ yield key
+
+ def keys(self):
+ sortKeys = self.sortAllKeys()
+ batch_start = self.batch_start or 0
+ batch_size = self.batch_size or 0
+ if not self.batch_size:
+ if not batch_start:
+ for k in sortKeys:
+ yield k
+ raise StopIteration
+ batch_end = None
+ else:
+ batch_end = batch_start + batch_size
+ for i, key in enumerate(sortKeys):
+ if batch_end is not None and i >= batch_end:
+ return
+ if i >= batch_start:
+ yield key
+
+ def values(self):
+ for k in self.keys():
+ yield self.context[k]
+
+ def items(self):
+ for k in self.keys():
+ yield k, self.context[k]
+
+ def __iter__(self):
+ return iter(self.keys())
+
+ def __getitem__(self, key):
+ '''See interface `IReadContainer`'''
+ if key in self.keys():
+ return self.context[key]
+ else:
+ raise KeyError, key
+
+ def get(self, key, default=None):
+ '''See interface `IReadContainer`'''
+ try:
+ return self.__getitem__(key)
+ except KeyError:
+ return default
+
+ def __len__(self):
+ '''See interface `IReadContainer`'''
+ return len(self.keys())
+
+ def __contains__(self, key):
+ '''See interface `IReadContainer`'''
+ return key in self.keys()
+
+ has_key = __contains__
+
+ def __setitem__(self, key, object):
+ '''See interface `IWriteContainer`'''
+ self.context.__setitem__(key, object)
+
+ def __delitem__(self, key):
+ '''See interface `IWriteContainer`'''
+ if key in self.keys():
+ self.context.__delitem__(key)
+ else:
+ raise KeyError, key
Modified: zope3org/trunk/src/zorg/multiform/gridform.txt
===================================================================
--- zope3org/trunk/src/zorg/multiform/gridform.txt 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/gridform.txt 2006-04-11 14:39:57 UTC (rev 66854)
@@ -25,7 +25,7 @@
... self.name = name
... self.__name__= name
- >>> orderMapping = dict([('n%s'%k,Order(k,name='n%s'%k)) for k in range(2)])
+ >>> orderMapping = dict([('n%s'%k,Order(k,name='n%s'%k)) for k in range(4)])
Now we use the ``GridForm`` as a base class to display orders in
tabular form. Additionally to the IOrder schema the ISelection schema
@@ -115,6 +115,7 @@
<div><input ... name="form.n1.selected" type="checkbox" ... /></div>
<div>1</div>
<div>n1</div>
+ ...
</div>
Also the edit action should be available.
@@ -141,6 +142,7 @@
<div><input... checked="checked" ... name="form.n1.selected" ... /></div>
<div>1</div>
<div>n1</div>
+ ...
</div>
By using the Edit action we can now switch all selected item forms to
@@ -150,6 +152,8 @@
>>> request.form['form.actions.edit']=u''
>>> request.form['form.n0.selected.used']=u''
>>> request.form['form.n1.selected']=u'on'
+ >>> request.form['form.n2.selected.used']=u''
+ >>> request.form['form.n3.selected.used']=u''
>>> gf = OrdersForm(orderMapping,request)
>>> res = gf()
>>> ISelection(gf.subForms['n1'].context).selected
@@ -164,6 +168,7 @@
<div><input... checked="checked" ... name="form.n1.selected" ... /></div>
<div>1</div>
<div><input... name="form.n1.name" ...</div>
+ ...
</div>
Also the edit action should be disabled now and the save action should
@@ -189,4 +194,86 @@
>>> request.form['form.n1.selected.used']=u''
>>> request.form['form.n1.actions.singleedit']=u''
>>> gf = OrdersForm(orderMapping,request)
- >>> res = gf()
+ >>> res = gf()
+
+The gridform class is able to handle batch_start and batch_size. Let us reduce
+the output.
+
+ >>> request = TestRequest()
+ >>> request.form['form.handle.batch_start']=1
+ >>> request.form['form.handle.batch_size']=2
+ >>> gf = OrdersForm(orderMapping,request)
+ >>> gf.update()
+ >>> print gf.render()
+ <div>
+ <div><input ... name="form.n1.selected" type="checkbox" ... /></div>
+ <div>1</div>
+ <div>n1</div>
+ </div>
+ <div>
+ <div><input ... name="form.n2.selected" type="checkbox" ... /></div>
+ <div>2</div>
+ <div>n2</div>
+ </div>
+
+Check the results of fraktal informations about batch_size and batch_start:
+
+ >>> request = TestRequest()
+ >>> request.form['form.handle.batch_start']=1
+ >>> gf = OrdersForm(orderMapping,request)
+ >>> gf.update()
+ >>> sorted([name for name in gf.subForms])
+ ['n1', 'n2', 'n3']
+ >>> request = TestRequest()
+ >>> request.form['form.handle.batch_size']=2
+ >>> gf = OrdersForm(orderMapping,request)
+ >>> gf.update()
+ >>> sorted([name for name in gf.subForms])
+ ['n0', 'n1']
+
+
+Sorting
+-------
+We can sort the grid with the informations field name (string) and
+reverse (bool).
+
+ >>> class Orders2Form(gridform.GridFormBase):
+ ... itemFormFactory=OrderForm
+ ... def template(self):
+ ... res = u''
+ ... for form in self.getForms():
+ ... res += '<div>%s</div>\n' % form.render()
+ ... return res
+ ...
+ ... @form.action('Cancel',condition=multiform.isFormInputMode)
+ ... def handle_cancel_action(self, action, data):
+ ... for form in self.subForms.values():
+ ... form.newInputMode = False
+
+ >>> orderMapping2 = dict([('n%s'%k,Order(4-k,name='n%s'%k)) for k
+ ... in range(4)])
+
+We sort the forms by the value of the column name
+
+ >>> request = TestRequest()
+ >>> request.form['form.handle.sort_on']=u'name'
+ >>> gf = Orders2Form(orderMapping2,request)
+ >>> gf.update()
+ >>> [(form.context.identifier,
+ ... form.context.name) for form in gf.getForms()]
+ [(4, 'n0'), (3, 'n1'), (2, 'n2'), (1, 'n3')]
+
+and reserve.
+
+ >>> request = TestRequest()
+ >>> request.form['form.handle.sort_on']=u'name'
+ >>> request.form['form.handle.sort_reverse']=u'on'
+ >>> gf = Orders2Form(orderMapping2,request)
+ >>> gf.update()
+ >>> [(form.context.identifier,
+ ... form.context.name) for form in gf.getForms()]
+ [(1, 'n3'), (2, 'n2'), (3, 'n1'), (4, 'n0')]
+
+TODO:
+-----
+- test singleedit, singlesave
\ No newline at end of file
Modified: zope3org/trunk/src/zorg/multiform/interfaces.py
===================================================================
--- zope3org/trunk/src/zorg/multiform/interfaces.py 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/interfaces.py 2006-04-11 14:39:57 UTC (rev 66854)
@@ -3,6 +3,7 @@
from zope import schema
from zope.formlib.i18n import _
+
class IMultiForm(Interface):
"""multiform"""
@@ -11,16 +12,20 @@
"""a sub form for an item of a multiform"""
+
class IGridItemForm(IItemForm):
"""an form for an item of a grid form"""
+
class IGridForm(IMultiForm):
"""a special grid multiform"""
+
class IItemAction(IAction):
"""a item action"""
+
class IParentAction(IAction):
"""a parent action"""
@@ -32,6 +37,13 @@
selected = schema.Bool(title=_(u'Selected'),default=False)
+
class IFormLocation(Interface):
__form_name__ = Attribute('The unique name of the item in a multiform')
+
+
+class ISorter(Interface):
+
+ def sort(items):
+ """return the items sorted. items are (key,value) tuples"""
Modified: zope3org/trunk/src/zorg/multiform/multiform.py
===================================================================
--- zope3org/trunk/src/zorg/multiform/multiform.py 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/multiform.py 2006-04-11 14:39:57 UTC (rev 66854)
@@ -140,22 +140,23 @@
implements(IMultiForm)
itemFormFactory = ItemFormBase
subForms={}
+ subFormsList = []
form_fields = []
actions = []
subActionNames = []
subFormInputMode = {}
selection = []
actions = []
-
+
def update(self):
self.checkInputMode()
self.updateSelection()
super(MultiFormBase,self).update()
hasErrors = False
- for form in self.subForms.values():
+ for form in self.getForms():
form.update()
refresh = False
- for form in self.subForms.values():
+ for form in self.getForms():
if form.newInputMode is not None:
newInputMode = form.newInputMode
context = self.context[form.context.__name__]
@@ -168,7 +169,6 @@
def setUpWidgets(self, *args, **kw):
super(MultiFormBase,self).setUpWidgets(*args,**kw)
- self.subForms = {}
self.setUpForms(*args, **kw)
def setUpForm(self, name, item, inputMode, *args, **kw):
@@ -185,14 +185,21 @@
self.subForms[name] = subForm
def setUpForms(self, *args, **kw):
- for name,item in self.context.items():
+ self.subForms = {}
+ self.subFormsList = []
+ for name, item in self.context.items():
inputMode = self.subFormInputMode.get(name,self.itemFormFactory.inputMode)
self.setUpForm(name, item, inputMode)
+ self.subFormsList.append(name)
self.refreshSubActionNames()
+ def getForms(self):
+ for name in self.subFormsList:
+ yield self.subForms[name]
+
def refreshSubActionNames(self):
availableActions = set()
- for subForm in self.subForms.values():
+ for subForm in self.getForms():
availableActions.update([action.__name__ for action in \
subForm.availableParentActions()])
self.subActionNames = []
@@ -263,7 +270,7 @@
action.__name__ = name
yield action
-
+
class SelectionForm(form.FormBase):
def __init__(self, context, request, form_fields):
Modified: zope3org/trunk/src/zorg/multiform/tests.py
===================================================================
--- zope3org/trunk/src/zorg/multiform/tests.py 2006-04-11 14:38:18 UTC (rev 66853)
+++ zope3org/trunk/src/zorg/multiform/tests.py 2006-04-11 14:39:57 UTC (rev 66854)
@@ -11,6 +11,7 @@
import gridform
import multiform
import selection
+import sort
from zope.formlib import form
def setUp(test):
@@ -70,7 +71,12 @@
[interfaces.IFormLocation],
interfaces.ISelection
)
-
+ component.provideAdapter(
+ sort.SchemaSorter,
+ [zope.interface.Interface,
+ zope.schema.interfaces.IField],
+ interfaces.ISorter
+ )
component.provideAdapter(gridform.default_grid_template,
name="default")
component.provideAdapter(gridform.default_griditem_template,
More information about the Checkins
mailing list