On Wed, 14 Feb 2007 19:22:53 +0100 Philipp von Weitershausen wrote: > Vinny wrote: > > In a ZPT I would do something like: > > > > for field in fieldsInObject(row) # which has (ordered?) fields > > th cell: field.name > > for row in rowView > > for field in fieldsInObject(row) # which has (ordered?) fields > > td cell: field.value > > > > I know the above is broken in several ways. I've been > > trying various methods all evening. The closest I get > > is the __dict__ usage. Ideally, I would get the > > interface provided by the object and feed that to > > form.Fields() but I can't determine how to get an > > interface value that can be fed to form.Fields(). > > > > iface = zope.interface.providedBy(obj) > > > > doesn't seem to work. > > By itself it won't work. You'll have to do a bit more. First of all, > an object can provide 0, 1 or more interfaces. Second, schemas are > just interfaces whose specifications are fields (a schema can also > have method specifications, there's no restriction to "mixing" a > traditional interface with a schema). Therefore: > > for iface in zope.interface.providedBy(obj): > for name in iface: > field = iface[name] > if zope.schema.interfaces.IField.providedBy(field): > # you've got a schema field, now you can work with > # field.title, field.description, etc. (see IField) >
Thank you Philipp, I have achieved my goal of a generic page template and sql container view. There are a few quick questions in the example code below. Mainly on being more efficient. Here are the results for everyone to use/comment on. Note that if anyone wants the rest of the files for this app., just let me know and I'll see what I can arrange. I still have to test it with more tables. ========== iso639.py snippet ========= from zope.publisher.browser import BrowserView from zope.security.proxy import removeSecurityProxy from zope.app import zapi import zope.interface from zope.sequencesort import sort from zope.app.preference import UserPreferences class SQLAlchemyContainerView(BrowserView): def __init__(self, context, request): self.context = context self.request = request def rowView(self): """ Presumably I have an instance of SQLAlchemyContainer We will be yielding a list of dictionaries with name and value keys. Philipp von Weitershausen provided some help on how to get to the schema/IField interface. """ sqlRecordObjects = [sqlRecordObject for sqlRecordObject in self.context.values()] sort_on = (('lookup', 'nocase', 'asc'),) sorted_rows = sort(sqlRecordObjects, sort=sort_on) #userPreferences = UserPreferences() # print userPreferences.hello.sorting.sortGroups #sorted_rows = sort(sqlRecordObjects, sort=userPreferences.hello.sorting.sortGroups) for sqlRecordObject in sorted_rows: sqlRecordObject = removeSecurityProxy(sqlRecordObject) nameValues = [] # A list of two-term dictionaries for iface in zope.interface.providedBy(sqlRecordObject): for name in iface: field = iface[name] if zope.schema.interfaces.IField.providedBy(field): # We've got a schema field, now we can work with # field.title, field.description, etc. (see IField) # Since we get a 'bonus' item in our schema called __name__ # we must ignore it. We use a list containment condition in # case we want to expand the list of ignored if field.__name__ in ['__name__']: pass else: #print (field.__name__, sqlRecordObject.__dict__[field.__name__], ) nameValues.append({'name': field.title, 'value': sqlRecordObject.__dict__[field.__name__]}) #print nameValues[key] # At this point we yield a list of dictionaries. # The dictionary has keys 'name' and 'value' and their values are, # respectively, the schema field title and # the value of the sql record's column yield nameValues def fieldsInObject(self): objlist = [obj for obj in self.context.values()] # oneLang = self.context.values(0) sqlRecordObject = removeSecurityProxy(objlist[0]) # Note: there *must* be a better way of getting # just one value from the container. Anyone have a # quick clue for me? fieldCount = 0 # I imagine there is a better way of getting the # number of fields in a schema than that shown below. for iface in zope.interface.providedBy(sqlRecordObject): for name in iface: field = iface[name] if zope.schema.interfaces.IField.providedBy(field): # We've got a schema field, now we can work with # field.title, field.description, etc. (see IField) # Since we get a 'bonus' item in our schema called __name__ # we must ignore it. We use a list containment condition in # case we want to expand the list of ignored attributes. if field.__name__ in ['__name__']: pass else: #print (field.__name__, sqlRecordObject.__dict__[field.__name__], ) fieldCount += 1 return fieldCount def sqlItemCount(self): # Seems we have to use removeSecurityProxy # often to avoid ForbiddenAttribute errors return len(removeSecurityProxy(self.context)) ========================== I'd appreciate it if someone could please answer either of the questions in the comments within the fieldsInObject method. ========= rowView.pt ============ <metal:block use-macro="context/@@standard_macros/view"> <tal:block metal:fill-slot="body" define="rows view/rowView; colspan view/fieldsInObject; recordcount view/sqlItemCount"> <table border="1"> <tal:block repeat="row rows" i18n:domain="hello"> <!-- the first row is a header showing a record count --> <tr tal:condition="repeat/row/start"> <th colspan="8" tal:attributes="colspan colspan" i18n:translate="record-count"> Number of items: <span i18n:name="recordcount" tal:omit-tag="" tal:content="recordcount">9</span> </th> </tr> <!-- the second row is a header showing field names --> <tr tal:condition="repeat/row/start"> <tal:cellloop repeat="field row"> <th tal:content="field/name">name</th> </tal:cellloop> </tr> <!-- The rest of the rows are data --> <tr> <tal:cellloop repeat="field row"> <td tal:content="field/value">value</td> </tal:cellloop> </tr> </tal:block> </table> </tal:block> </metal:block> =============================================== The code is very much 'draft' quality and can stand improvement, of course. For example, robustness requires more error checking, catching, and handling. We should probably sort in the database, and so on. Regards, Vinny _______________________________________________ Zope3-users mailing list Zope3-users@zope.org http://mail.zope.org/mailman/listinfo/zope3-users