In my TG CRUD work, I generate edit form, view list and view screen from SQLObject. I use the similar approach of Kevin : using *arg or a list in the contrustor of a CompositeWidget. I also add an append() method. Advantages of this solution : * easy to create and extends a form automaticaly ... editWidgetMap = { 'container' : widget4edit.FormWidgetsList, 'default' : widget4edit.TextLineWidget, 'SOStringCol': widget4edit.TextLineWidget, 'SOStringCol+long': widget4edit.TextWidget, 'SOUnicodeCol': widget4edit.TextLineWidget, 'SOUnicodeCol+long': widget4edit.TextWidget, 'SOBoolCol': widget4edit.CheckBoxWidget, 'SOForeignKey' : widget4edit.VocabularyWidget, 'SOEnumCol' : widget4edit.VocabularyWidget, # 'SOIntCol':IntWidget, # 'SODateTimeCol':DateTimeWidget }
def buildWidgetsList(self, sqlobj, widgetmap): """ @param sqlobj the type (like app.model.Page) for wich create a WidgetContainer @param widgetmap the family of widgets to use for each SQLObject field type """ back = [] columns = sqlobj.sqlmeta.columns for col in sqlobj.sqlmeta.columnList: name = col.origName clazz = col.__class__.__name__ if (clazz == 'SOStringCol' or clazz == 'SOUnicodeCol') and not(col.length): clazz += '+long' widget = widgetmap.get(clazz, widgetmap['default'])(key=name) if hasattr(widget, 'vocabulary') and (widget.vocabulary is None): if clazz == 'SOForeignKey': referencedsql = findClass(col.foreignKey) widget.vocabulary = SQLVocabulary(referencedsql) elif clazz == 'SOEnumCol': widget.vocabulary = widgetsupport.Vocabulary(col.enumValues) if hasattr(widget, 'defaultValue') and (widget.defaultValue is None): widget.defaultValue = col.enumValues[0] if hasattr(widget, 'required') and (widget.required is None): widget.required = col.notNone if hasattr(widget, 'validator') and (widget.validator is None): widget.validator = col.validator back.append(widget) return widgetmap['container'](*back) #IGNORE:W0142 ... * the WidgetContainer instance could be attach to a SQLObject type. In my case after building a WidgetContainer I do : if not(hasattr(sqlobj, 'editWidget')): #autogeneration of the editwidget sqlobj.editWidget = self.buildWidgetsList(sqlobj, self.editWidgetMap) sqlobj.editWidget.append(widget4edit.HiddenWidget('isNew', validators.Bool(), True)) sqlobj.editWidget.append(widget4edit.HiddenWidget('id', validators.Int(), -1)) * you could create 2 instances of the same WidgetContainer, an each one could have it's own internal state without interference, like 2 instances of TextField... (may be my java background influence me too much, but class state/field are share by all instance, and there is only one class definition available in the system) my 2 cents