Richtext stored in plone.app.registry

I'm looking for recommendations on how to store RichText in plone.app.registry
I've defined the following for a controlpanel:

# -*- coding: utf-8 -*-
from plone.app.registry.browser.controlpanel import ControlPanelFormWrapper
from plone.app.registry.browser.controlpanel import RegistryEditForm
from plone.z3cform import layout
from plone.app.textfield import RichText
from zope import schema
from zope.interface import Interface


class IAnnouncementControlPanel(Interface):

    site_announcement = RichText(
        title=u'A announcement that shows on the website',
        required=False,
    )

    show_on_all_pages = schema.Bool(
        title=u'Show on All Pages',
        description=u'Show on all pages not just the front page',
        default=False,
        required=False,
    )


class AnnouncementControlPanelForm(RegistryEditForm):
    schema = IAnnouncementControlPanel
    schema_prefix = "site_announcement"
    label = u'Announcement Settings'


AnnouncementControlPanelView = layout.wrap_form(
    AnnouncementControlPanelForm, ControlPanelFormWrapper)

I thought it was as easy as defining a schema with RichText, but I get the following error:

Module plone.registry.registry, line 95, in registerInterface
TypeError: There is no persistent field equivalent for the field `site_announcement` of type `RichText`.

The value of a plone.app.textfield.RichText field is a plone.app.textfield.value.RichTextValue object. But you can only store primitive python datatypes in plone.app.registry, not abitrary objects. See: https://github.com/plone/plone.registry/blob/master/plone/registry/field.py

I see two options:

1 Like

I went with this basically changing the default widget but still storing it as plain text:

from z3c.form.interfaces import INPUT_MODE
from z3c.form import form, field
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget

....

class AnnouncementControlPanelForm(RegistryEditForm):
    fields = field.Fields(IAnnouncementControlPanel)
    fields['site_announcement'].widgetFactory[INPUT_MODE] = WysiwygFieldWidget
    schema = IAnnouncementControlPanel
    # this should give us a richtext widget for editing
    schema_prefix = "site_announcement"
    label = u'Announcement Settings'

So far so good.

4 Likes

it's not pretty clear to non-hardcore developers how to create a PersistentField as proposed in your answer; I checked the source but a pattern is not obvious.

here's an alternate solution for people using z3c.form based forms and plone.autoform instead:

from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
from plone.autoform import directives as form
from plone.supermodel import model
from zope import schema

class IDisclaimerSettings(model.Schema):
    ...

    form.widget('text', WysiwygFieldWidget)
    text = schema.Text(
        title=_(u'Body text'),
        description=_(u'The text of the disclaimer.'),
        required=True,
    )
1 Like

please note the plone.app.z3cform.wysiwyg.WysiwygFieldWidget is deprecated as per Plone 5.1:

What should we use instead? Would be nice if those deprecation messages said something a bit more helpful.

completely unrelated, but with theme fragments I (once) had a similar problem that I hacked around by using the rich text mockup pattern. You can set the class (klass="pat-tinymce") in the schema (but I am not sure if you can set other options)

1 Like

This works in both Plone versions:

from plone import api
from plone.autoform import directives as form
from plone.supermodel import model
from zope import schema

IS_PLONE_5 = api.env.plone_version().startswith('5')

class IDisclaimerSettings(model.Schema):
    ...

    if IS_PLONE_5:
        form.widget('text', klass='pat-tinymce')
    else:
        from plone.app.z3cform.wysiwyg import WysiwygFieldWidget
        form.widget('text', WysiwygFieldWidget)
    text = schema.Text(
        title=_(u'Body text'),
        description=_(u'The text of the disclaimer.'),
        required=True,
    )

UPDATE: You can check the pull request on the real package: https://github.com/collective/disclaimer/pull/3/files

2 Likes

Thanks!

I thought I'd post my working code too:

    widget('program_view_footer', klass='pat-tinymce' ) # works for Plone 5.x
    # widget(program_view_footer=WysiwygFieldWidget) # results in deprecation warnings but works ok in Plone 5.0
    program_view_footer = schema.Text(
        title=_(u'Program Footer Text'),
        description=_(u'will appear at bottom of public program view'),
        required=False,
        missing_value=None,
        default=None,
    )