list the fields of a dexterity object
Asked Answered
S

6

8

I'd like to list all the fields (and the values) of a dexterity object.

I can easily access a single field value like this myobject.myfield

But I don't know how to list all the available fields of an object.

Spake answered 29/8, 2012 at 13:6 Comment(0)
E
8

Dexterity objects are defined by a schema, which is enumerable:

from zope.interface.interfaces import IMethod

for name, desc in IYourDexteritySchema.namesAndDescriptions():
    value = getattr(yourDexterityInstance, name)
    if IMethod.providedBy(desc):
        # It's a method, call it
        value = value()

Here I use the .namesAndDescriptions() method, but you can also just use the interface as an iterator if you don't have any methods on your schema:

for name in IYourDexteritySchema:
    value = getattr(yourDexterityInstance, name)

Last but not least, zope.schema has a utility method named getFieldsInOrder that will filter on zope.schema fields in an interface; the above methods also list methods and non-schema attributes, getFieldsInOrder only lists zope.schema specific attribute types:

from zope.schema import getFieldsInOrder

for name, field in getFieldsInOrder(IYourDexteritySchema):
    value = getattr(yourDexterityInstance, name)

If you defined the schema through-the-web, you may not know how to look up the interface for your type. You can also retrieve the schema interface through the Factory Type Information, or FTI for short:

from plone.dexterity.interfaces import IDexterityFTI
from zope.component import getUtility

schema = getUtility(IDexterityFTI, name='your.dexterity.type').lookupSchema()

where schema now holds your interface.

Endowment answered 29/8, 2012 at 13:9 Comment(1)
Note: All of the answers here only give the fields on the main interface, not fields that may be added by behaviors. Unfortunately those are figured out as part of rendering forms, and there isn't currently a good way to enumerate them all outside the form rendering process.Tinney
L
7

as David noted, I could not find a way to enumerate the fields coming from behaviors.

So, digging into plone.dexterity, in utils.getAdditionalSchemata function I found this way to roughly solve the problem:

from zope.schema import getFieldsInOrder
from plone.behavior.interfaces import IBehaviorAssignable

behavior_assignable = IBehaviorAssignable(context)
if behavior_assignable:
  behaviors = behavior_assignable.enumerateBehaviors()
  for behavior in behaviors:
    for k,v in getFieldsInOrder(behavior.interface):
      # ...
Laplante answered 26/9, 2012 at 11:22 Comment(1)
Note that this will only get behaviours, so you need to do both. :-)Baroque
S
5

I found a way to do it. Since the dexterity scheme varies I could not use Christophs suggestion directly. But this works now

for key, value in getFieldsInOrder(obj.getTypeInfo().lookupSchema()):
    value = getattr(getattr(obj, key), 'output', getattr(obj, key))
Spake answered 29/8, 2012 at 14:34 Comment(0)
I
1

You can alternatively use the FTI:

from plone.dexterity.interfaces import IDexterityFTI
from zope.component import getUtility

fti = getUtility(IDexterityFTI, name='rgd.venues.venue')
schema = fti.lookupSchema()
fields = getFieldsInOrder(schema)
for key, value in fields:
    # so something
Illuminative answered 29/8, 2012 at 13:15 Comment(1)
Nice, but again: this only works for schema fields, not behaviorGauhati
I
1

Figure out how to list all fields from fields and behaviors:

from plone.behavior.interfaces import IBehavior
from plone.dexterity.interfaces import IDexterityFTI
from zope.component import getUtility


def get_fields(portal_type):
    fti = getUtility(IDexterityFTI, name=portal_type)
    schema = fti.lookupSchema()
    fields = schema.names()
    for bname in fti.behaviors:
        factory = getUtility(IBehavior, bname)
        behavior = factory.interface
        fields += behavior.names()
    return fields
Informant answered 12/11, 2018 at 21:56 Comment(0)
S
1

You can use iterSchemata and getFieldsInOrder:

from plone.dexterity.utils import iterSchemata
from zope.schema import getFieldsInOrder

for schema in iterSchemata(obj):
    print(u'  %s' % schema)
    for field in getFieldsInOrder(schema):
        print(u'    %s\t%s' % field)

if obj is a Document it outputs

plone.dexterity.schema.generated.Plone_5_1643036771_2_583572_0_Document
plone.app.dexterity.behaviors.discussion.IAllowDiscussion
  allow_discussion    plone.app.dexterity.behaviors.discussion.IAllowDiscussion.allow_discussion
plone.app.dexterity.behaviors.exclfromnav.IExcludeFromNavigation
  exclude_from_nav    plone.app.dexterity.behaviors.exclfromnav.IExcludeFromNavigation.exclude_from_nav
plone.app.dexterity.behaviors.id.IShortName
  id  plone.app.dexterity.behaviors.id.IShortName.id
plone.app.dexterity.behaviors.metadata.IDublinCore
  title       plone.app.dexterity.behaviors.metadata.IBasic.title
  description plone.app.dexterity.behaviors.metadata.IBasic.description
  subjects    plone.app.dexterity.behaviors.metadata.ICategorization.subjects
  language    plone.app.dexterity.behaviors.metadata.ICategorization.language
  effective   plone.app.dexterity.behaviors.metadata.IPublication.effective
  expires     plone.app.dexterity.behaviors.metadata.IPublication.expires
  creators    plone.app.dexterity.behaviors.metadata.IOwnership.creators
  contributors        plone.app.dexterity.behaviors.metadata.IOwnership.contributors
  rights      plone.app.dexterity.behaviors.metadata.IOwnership.rights
plone.app.contenttypes.behaviors.richtext.IRichTextBehavior
  text        plone.app.contenttypes.behaviors.richtext.IRichTextBehavior.text
plone.app.relationfield.behavior.IRelatedItems
  relatedItems        plone.app.relationfield.behavior.IRelatedItems.relatedItems
plone.app.versioningbehavior.behaviors.IVersionable
  changeNote  plone.app.versioningbehavior.behaviors.IVersionable.changeNote
  versioning_enabled  plone.app.versioningbehavior.behaviors.IVersionable.versioning_enabled
plone.app.contenttypes.behaviors.tableofcontents.ITableOfContents
  table_of_contents   plone.app.contenttypes.behaviors.tableofcontents.ITableOfContents.table_of_contents
Speller answered 24/1, 2022 at 16:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.