add keytable stuff to grid-like field definitions
This commit is contained in:
parent
3e5b4d2bff
commit
4c2f79d929
3 changed files with 130 additions and 23 deletions
|
@ -2,8 +2,6 @@
|
||||||
Schema and Field Management
|
Schema and Field Management
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
>>> from cybertools.composer.schema import Schema
|
>>> from cybertools.composer.schema import Schema
|
||||||
>>> from cybertools.composer.schema import Field
|
>>> from cybertools.composer.schema import Field
|
||||||
|
|
||||||
|
@ -193,3 +191,58 @@ Macros / renderers
|
||||||
[u'field', u'field_spacer', u'fields', u'form', u'input_checkbox',
|
[u'field', u'field_spacer', u'fields', u'form', u'input_checkbox',
|
||||||
u'input_date', u'input_dropdown', u'input_fileupload', u'input_html',
|
u'input_date', u'input_dropdown', u'input_fileupload', u'input_html',
|
||||||
u'input_list', u'input_password', u'input_textarea', u'input_textline']
|
u'input_list', u'input_password', u'input_textarea', u'input_textline']
|
||||||
|
|
||||||
|
|
||||||
|
Special Field Types
|
||||||
|
===================
|
||||||
|
|
||||||
|
Grids, Records, Key Tables
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
>>> from cybertools.composer.schema.grid.field import KeyTableFieldInstance
|
||||||
|
|
||||||
|
>>> ktfield = Field('data')
|
||||||
|
>>> ktfield.column_types = [zope.schema.Text(__name__='key', title=u'Key',),
|
||||||
|
... zope.schema.Text(__name__='value', title=u'Value')]
|
||||||
|
|
||||||
|
>>> ktfi = KeyTableFieldInstance(ktfield)
|
||||||
|
>>> ktfi.unmarshall([dict(key='0001', value='First row')])
|
||||||
|
{u'0001': [u'First row']}
|
||||||
|
|
||||||
|
>>> ktfi.marshall({u'0001': [u'First row']})
|
||||||
|
[{'value': u'First row', 'key': u'0001'}]
|
||||||
|
|
||||||
|
Now with some real stuff, using a field instance that takes the column types
|
||||||
|
from the context object of the edit form.
|
||||||
|
|
||||||
|
>>> from cybertools.composer.schema.grid.interfaces import KeyTable
|
||||||
|
>>> from cybertools.composer.schema.grid.field import \
|
||||||
|
... ContextBasedKeyTableFieldInstance
|
||||||
|
>>> component.provideAdapter(ContextBasedKeyTableFieldInstance, name='keytable')
|
||||||
|
|
||||||
|
>>> class IDataTable(Interface):
|
||||||
|
... title = zope.schema.TextLine(title=u'Title', required=False)
|
||||||
|
... columnNames = zope.schema.List(title=u'Column Names', required=False)
|
||||||
|
... data = KeyTable(title=u'Data', required=False)
|
||||||
|
>>> IDataTable['columnNames'].nostore = True
|
||||||
|
|
||||||
|
>>> class DataTable(object):
|
||||||
|
... implements(IDataTable)
|
||||||
|
... def __init__(self, title, columnNames):
|
||||||
|
... self.title = title
|
||||||
|
... self.columnNames = columnNames
|
||||||
|
|
||||||
|
>>> dt = DataTable('Account Types', ['identifier', 'label', 'info'])
|
||||||
|
|
||||||
|
>>> input = dict(title='Account Types',
|
||||||
|
... columnNames=['identifier', 'label', 'info'],
|
||||||
|
... data=[dict(identifier='0001', label='Standard', info='')],
|
||||||
|
... action='update')
|
||||||
|
>>> form = Form(dt, TestRequest(form=input))
|
||||||
|
>>> form.interface = IDataTable
|
||||||
|
>>> form.nextUrl = 'dummy_url'
|
||||||
|
>>> form.update()
|
||||||
|
False
|
||||||
|
|
||||||
|
>>> dt.data
|
||||||
|
{u'0001': [u'Standard', u'']}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Field and field instance classes for grids.
|
Field and field instance classes for grids.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope import component
|
from zope import component
|
||||||
|
@ -30,7 +28,7 @@ from zope.cachedescriptors.property import Lazy
|
||||||
import zope.schema
|
import zope.schema
|
||||||
|
|
||||||
from cybertools.composer.schema.factory import createField
|
from cybertools.composer.schema.factory import createField
|
||||||
from cybertools.composer.schema.field import ListFieldInstance
|
from cybertools.composer.schema.field import Field, ListFieldInstance
|
||||||
from cybertools.composer.schema.interfaces import IField, IFieldInstance
|
from cybertools.composer.schema.interfaces import IField, IFieldInstance
|
||||||
from cybertools.composer.schema.interfaces import fieldTypes, undefined
|
from cybertools.composer.schema.interfaces import fieldTypes, undefined
|
||||||
from cybertools.util.format import toStr, toUnicode
|
from cybertools.util.format import toStr, toUnicode
|
||||||
|
@ -91,6 +89,13 @@ class GridFieldInstance(ListFieldInstance):
|
||||||
return []
|
return []
|
||||||
result = []
|
result = []
|
||||||
rows = json.loads(value)['items']
|
rows = json.loads(value)['items']
|
||||||
|
for row in rows:
|
||||||
|
item = self.unmarshallRow(row)
|
||||||
|
if item:
|
||||||
|
result.append(item)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def dummy(self):
|
||||||
for row in rows:
|
for row in rows:
|
||||||
item = {}
|
item = {}
|
||||||
empty = True
|
empty = True
|
||||||
|
@ -106,6 +111,18 @@ class GridFieldInstance(ListFieldInstance):
|
||||||
result.append(item)
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def unmarshallRow(self, row):
|
||||||
|
item = {}
|
||||||
|
for fi in self.columnFieldInstances:
|
||||||
|
value = fi.unmarshall(row[fi.name])
|
||||||
|
if isinstance(value, basestring):
|
||||||
|
value = value.strip()
|
||||||
|
if fi.default is not None:
|
||||||
|
if value == fi.default:
|
||||||
|
continue
|
||||||
|
item[fi.name] = value
|
||||||
|
return item
|
||||||
|
|
||||||
|
|
||||||
class RecordsFieldInstance(GridFieldInstance):
|
class RecordsFieldInstance(GridFieldInstance):
|
||||||
|
|
||||||
|
@ -123,19 +140,49 @@ class RecordsFieldInstance(GridFieldInstance):
|
||||||
value = []
|
value = []
|
||||||
result = []
|
result = []
|
||||||
for row in value:
|
for row in value:
|
||||||
item = {}
|
item = self.unmarshallRow(row)
|
||||||
empty = True
|
if item:
|
||||||
for fi in self.columnFieldInstances:
|
|
||||||
value = row[fi.name]
|
|
||||||
if isinstance(value, basestring):
|
|
||||||
value = value.strip()
|
|
||||||
value = fi.unmarshall(value)
|
|
||||||
item[fi.name] = value
|
|
||||||
if fi.default is not None:
|
|
||||||
if value and value != fi.default:
|
|
||||||
empty = False
|
|
||||||
elif value:
|
|
||||||
empty = False
|
|
||||||
if not empty:
|
|
||||||
result.append(item)
|
result.append(item)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class KeyTableFieldInstance(RecordsFieldInstance):
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def keyName(self):
|
||||||
|
return self.columnTypes[0].name
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def dataNames(self):
|
||||||
|
return [f.name for f in self.columnTypes[1:]]
|
||||||
|
|
||||||
|
def marshall(self, value):
|
||||||
|
result = []
|
||||||
|
if not value:
|
||||||
|
return result
|
||||||
|
for k, v in value.items():
|
||||||
|
item = {self.keyName: k}
|
||||||
|
for idx, name in enumerate(self.dataNames):
|
||||||
|
item[name] = v[idx]
|
||||||
|
result.append(item)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def unmarshall(self, value):
|
||||||
|
if not value:
|
||||||
|
value = {}
|
||||||
|
result = {}
|
||||||
|
for row in value:
|
||||||
|
item = self.unmarshallRow(row)
|
||||||
|
if item:
|
||||||
|
result[item.pop(self.keyName)] = [item.get(name)
|
||||||
|
for name in self.dataNames]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class ContextBasedKeyTableFieldInstance(KeyTableFieldInstance):
|
||||||
|
|
||||||
|
@Lazy
|
||||||
|
def columnTypes(self):
|
||||||
|
obj = self.clientInstance.context
|
||||||
|
return [Field(name) for name in obj.columnNames]
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2009 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Grid field definition.
|
Grid field definition.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope import schema
|
from zope import schema
|
||||||
|
@ -50,3 +48,12 @@ class Records(Grid):
|
||||||
u'A series of records or rows.',
|
u'A series of records or rows.',
|
||||||
instanceName='records',))
|
instanceName='records',))
|
||||||
|
|
||||||
|
|
||||||
|
class KeyTable(Grid):
|
||||||
|
|
||||||
|
__typeInfo__ = ('keytable',
|
||||||
|
FieldType('keytable', 'keytable',
|
||||||
|
u'A dictionary of records or rows the first '
|
||||||
|
u'column of which represents the key.',
|
||||||
|
instanceName='keytable',))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue