I have a custom DX content-types and collective.geolocationbehavior added to the CT through its FTI.
Now the geolocation field shows up default fieldset in edit mode. I need to move it to a different fieldset or its own fieldset.
Using this
fieldset('MyField', fields=['geolocation'])
inside my schema does work:
zope.configuration.config.ConfigurationExecutionError: <type 'exceptions.ValueError'>: The directive plone.supermodel.fieldsets applied to interface dynamore.policy.content.dynalocation.IDynalocation refers to unknown field name geolocation
in:
File "/home/ajung/sandboxes/plone-server-buildout-plone5/eggs/plone.supermodel-1.3.4-py2.7.egg/plone/supermodel/configure.zcml", line 9.4-12.10
<zcml:customAction
handler=".model.finalizeSchemas"
order="9999999"
/>
You can do this globally by moving the fields for all CTs using it (example showing the changeNote field, but can be applied to all other behaviors as well):
from plone.app.dexterity import _ as _DX
from plone.app.versioningbehavior.behaviors import IVersionable
from plone.supermodel.interfaces import FIELDSETS_KEY
from plone.supermodel.model import Fieldset
settings = Fieldset(
'settings',
label=_DX(u'Settings'),
fields=['changeNote'],
)
fieldsets = IVersionable.getTaggedValue(FIELDSETS_KEY)
fieldsets.append(settings)
Your (magic) example code works great! I initially thought it belonged in the class definition for the content type's interface but, in fact, it belongs outside of any class definition.
But I could not get it to work with lead image behaviour. It would result in this error. I don't know why ILeadImage would be different.
I know ILeadImage defines no fieldsets because calling ILeadImage.getTaggedValue(FIELDSETS_KEY) gives a KeyError. I used a try block to be more general here.
Warming up an old thread to dump my working code snippet here:
from plone.supermodel.interfaces import FIELDSETS_KEY
from plone.supermodel.model import Fieldset
def move_field(
schema, fieldname, to_fieldset_name, label=None, description=None, order=None
):
"""Moves a field named "fieldname" on a Zope "schema" to a new fieldset "to_field_name".
- creates a new fieldset on demand (then label, description and order are passed to the new one).
- if value of "to_fieldset_name" is "default", then the field sticks on the main form.
"""
# find schema with field in inheritance tree
schema_with_field = None
for pschema in reversed(schema.__iro__):
if pschema.direct(fieldname):
schema_with_field = pschema
break
if schema_with_field is None:
raise KeyError(f"field '{fieldname}' does not exist on {schema}.")
# remove field from fieldset (if in any)
fieldsets_direct = schema_with_field.queryDirectTaggedValue(FIELDSETS_KEY)
if fieldsets_direct is not None:
for fieldset in fieldsets_direct:
if fieldname in fieldset.fields:
fieldset.fields.remove(fieldname)
break
if to_fieldset_name == "default":
# default means to fieldset, but on main form
return
if fieldsets_direct is None:
# no tagged value set so far!
fieldsets_direct = list()
schema.setTaggedValue(FIELDSETS_KEY, fieldsets_direct)
# try to find the fieldset, append and exit
for fieldset in fieldsets_direct:
if fieldset.__name__ == to_fieldset_name:
fieldset.fields.append(fieldname)
return
# not found, need to create new fieldset
new_fieldset = Fieldset(
to_fieldset_name,
fields=[fieldname],
)
if label is not None:
new_fieldset.label = label
if description is not None:
new_fieldset.description = description
if order is not None:
new_fieldset.order = order
fieldsets_direct.append(new_fieldset)
# Done!
# example
from plone.app.contenttypes.behaviors.leadimage import ILeadImageBehavior
from plone.app.dexterity.behaviors.metadata import ICategorization
from plone.app.dexterity.behaviors.metadata import IDublinCore
# 1) move direct field language on ICategorization from fieldset
# categorization to settings
move_field(ICategorization, "language", "settings")
# 2) move inherited field subject on IDublinCore from fieldset
# categorization to settings
move_field(IDublinCore, "subjects", "settings")
# 3) move inherited field image on ILeadImage from main form
# to new fiedset images
move_field(ILeadImageBehavior, "image", "images", label="Images", order=10)
We may want to have this in the utils.py of plone.supermodel or plone.autoform I suppose. Any volunteers?