简体   繁体   中英

Plone: Registry dict field with multiple fields values

I have an interface:

class ISomething(Interface):
    something = schema.Dict(
        title=u"Something",
        description=u"Define something.",
        key_type=schema.TextLine(title=u"Some Title"),
        value_type=schema.Text(title=u"Some Text"))

used to create a form that saves values in registry ( ControlPanelFormWrapper , RegistryEditForm ).

In registry.xml :

<record name="something">
  <field type="plone.registry.field.Dict">
    <title>Something</title>
    <key_type type="plone.registry.field.TextLine" />
    <value_type type="plone.registry.field.Text" />
  </field>
</record>

It's working: I can add key-value items {'Some Title': 'Some Text'} .

I need to modify my form to have multiple fields instead of Some text , but keeping the Dict . Example:

{'Some Title': { 'field_1': 'Value 1', 'field_2': 'Value 2' } }

I expect this to work then:

registry = getUtility(IRegistry)
reg_something = registry.get("something")
print reg_something['Some Title']['field_1']

>>> Value 1

So, how to change my interface and registry record to have the form updated in this way?

This is described in an article from Mark van Lent: https://www.vlent.nl/weblog/2011/09/07/dict-list-value-ploneappregistry/

Adjust the registry.xml accordingly, exchange the record-name with yours:

<record name="my.package.example">
 <field type="plone.registry.field.Dict">
   <title>Verification filesnames</title>
   <key_type type="plone.registry.field.TextLine">
     <title>Key</title>
   </key_type>
   <value_type type="plone.registry.field.List">
     <title>Value list</title>
     <value_type type="plone.registry.field.TextLine">
       <title>Values</title>
     </value_type>
   </value_type>
 </field>
 <value purge="false" />

See also this question where Luca Fabbri and Gil Forcada each provide alternative approaches, which might be true time-savers on the long term: Plone- How can I create a control panel for a record in registry that is a dictionary type?

registry.xml in my default profile (imported with an upgrade step):

<registry>
  <records interface="my.package.something.ISomethingItems">

    <record name="mypackage_multiplesomething">
      <field type="plone.registry.field.List">
        <title>Something Items</title>
        <value_type type="collective.z3cform.datagridfield.DictRow">
          <schema>my.package.something.ISomething</schema>
        </value_type>
      </field>
    </record>
  </records>
</registry>

In something.py just define the interfaces:

from collective.z3cform.datagridfield import BlockDataGridFieldFactory
from collective.z3cform.datagridfield.registry import DictRow
from plone import api
from plone.app.registry.browser.controlpanel import ControlPanelFormWrapper
from plone.app.registry.browser.controlpanel import RegistryEditForm
from plone.autoform import directives
from zope import schema
from zope.interface import Interface
from zope.interface import implementer
from zope.schema.interfaces import IVocabularyFactory
from zope.schema.vocabulary import SimpleTerm
from zope.schema.vocabulary import SimpleVocabulary


class ISomething(Interface):
    id = schema.ASCIILine(
        title=u"Something ID",
        description=u"Some description."
    )

    text = schema.Text(
        title=u"A text field",
        description=u"Human readable text"
    )

    url = schema.URI(
        title=u"An URL",
        description=u"Don't forget http:// or https://"
    )


class ISomethingItems(Interface):
    # the field is the same used in registry.xml
    mypackage_multiplesomething = schema.List(
        title=u"Something Items",
        description=u"Define something items",
        value_type=DictRow(title=u"Something", schema=ISomething)
    )
    directives.widget(mypackage_multiplesomething=BlockDataGridFieldFactory)

Now we can have an edit form (in something.py ):

class SomethingItemsEditForm(RegistryEditForm):

    schema = ISomethingItems
    label = u"Something items definition"


class SomethingItemsView(ControlPanelFormWrapper):
    """ Something items edit form """

    form = SomethingItemsEditForm

defined as browser page ( configure.zcml ):

  <browser:page
    name="something-items-settings"
    for="Products.CMFPlone.interfaces.IPloneSiteRoot"
    class=".something.SomethingItemsView"
    permission="cmf.ManagePortal"
    />

Easy to get the values from registry using api:

>>> from plone import api
>>> reg_something_items = api.portal.get_registry_record(
    'mypackage_somethingitems', interface=ISomethingItems)
[{'id': 'some id', 'text': 'some text', 'url': 'http://something.com'}, {'id': 'some id other', 'text': 'some text other', 'url': 'http://something-other.com'}]
>>> item = reg_something_items[0]
{'id': 'some id', 'text': 'some text', 'url': 'http://something.com'}
>>> item['id']
some id
>>> item['text']
some text
>>> item['url']
http://something.com

If you added an uninstall profile to your product it is a good idea to add registry.xml in it:

<registry>
  <record name="my.package.something.ISomethingItems.mypackage_somethingitems"
          delete="True" remove="True" />

</registry>

to be sure the registry will be clean after uninstall.

You can check anytime the values you have in registry in SITE/portal_registry (Site Setup -> Configuration Registry)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM