2015-02-24

Kotti CMS - how to store arbitrary data with annotations

With Kotti CMS you can extend existing types inheriting from a base class (eg: Document) and obtain another type of object (eg: MyDocument) with new fields, new workflows, custom views, custom addability conditions, etc.

But sometimes you may want to add a custom field to one or more resources, without having to create a new type. For example you might want to add a colour attribute to all existing Document objects, let's imagine a simple select widget with few colours that will be used for adding a class depending on the choosen colour.

By default Kotti is shipped with an annotations column that can be used to store arbitrary data in a nested dictionary.

You can store arbitrary data in the nested dictionary with a syntax similar to the following one:
context.annotations['SOMEKEY'] = VALUE
and read annotations with:
context.annotations
All you need to do is overriding the add and edit form of your target class. With Pyramid is quite easy to extending an existing application and override views, assets, routes, etc. See http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/extending.html for further info.

Here you can see one possible implementation:
from pyramid.view import view_config
import colander
from deform.widget import SelectWidget
from kotti_actions.views.edit.actions.link import (
    LinkActionAddForm as OriginalLinkActionAddForm,
    LinkActionEditForm as OriginalLinkActionEditForm,
    )
from kotti_actions.resources import (
    LinkAction
    )
...
        colours = [
            ('', 'Select'),
            ('red', 'Red'),
            ('brown', 'Brown'),
            ('beige', 'Beige'),
            ('blue', 'Blue'),
            ]

def add_colour(schema):
    schema['colour'] = colander.SchemaNode(
        colander.String(),
        title=_('Colour'),
        widget=SelectWidget(values=colours),
        missing=u"",
        )

@view_config(name=LinkAction.type_info.add_view, permission='add',
             renderer='kotti:templates/edit/node.pt')
class LinkActionAddForm(OriginalLinkActionAddForm):
    """ Form to add a new instance of CustomContent. """

    def schema_factory(self):
        schema = super(LinkActionAddForm, self).schema_factory()
        add_colour(schema)
        return schema

    def add(self, **appstruct):
        colour = u''
        try:
            colour = appstruct.pop('colour')
        except KeyError:
            pass
        obj = super(LinkActionAddForm, self).add(**appstruct)

        obj.annotations['colour'] = colour
        return obj


@view_config(name='edit', context=LinkAction, permission='edit',
             renderer='kotti:templates/edit/node.pt')
class LinkActionEditForm(OriginalLinkActionEditForm):
    """ Form to edit existing calendars. """

    def schema_factory(self):
        schema = super(LinkActionEditForm, self).schema_factory()
        add_colour(schema)
        return schema

    def before(self, form):
        super(LinkActionEditForm, self).before(form)
        colour = self.context.annotations.get('colour')
        if colour:
            form.appstruct.update({'colour': colour})

    def edit(self, **appstruct):
        super(LinkActionEditForm, self).edit(**appstruct)
        self.context.annotations['colour'] = appstruct['colour']

Now our LinkAction add and edit form will have an additional select with our colours.

All posts about Kotti

All Kotti posts published by @davidemoro:


No comments:

Post a Comment