Memoize / cache 'widget'

[ Forgive me for the possible awkward explanation, I am on virgin ground here' ]

I made a behavior with a text field that renders 'code/tags as html'.
The field uses a widget that transforms the tags to html (when viewing).

If I use a content type, I can probably use @memoize (?) to cache the field, instead of the transform happening every time the content is viewed.

But what if I just use the behavior and the default dexterity view… is there a way I can 'enable caching' in the widget or the behavior ?

The @memoize decorator from plone.memoize.view should work on everything that has a context and a request attribute.
I do believe a widget has both of them.

Thanks.

Obviously, I am doing something wrong here.
If I use @forever.memorize, it gets cached forever, but if I use just @memoize, it does not cache.

class IXtagsWidget(interfaces.IWidget):
    """Xtags widget."""


class XtagsWidget(text.TextWidget):
    """Xtags Widget"""

    @forever.memoize
    #@memoize
    def get_xtags(self):
        tagged_text = self.value
        log.info('getting xtags!')
        try:
            element_tree = to_xml(tagged_text, extra_tags_to_keep={}, css=True)
            serialised_xml = tostring(element_tree, encoding='utf-8')
            return serialised_xml

        except:
            return '<p class="error">[rendering error]<p>'

    zope.interface.implementsOnly(IXtagsWidget)

def XtagsFieldWidget(field, request):
    """IFieldWidget factory for XtagsWidget."""
    return widget.FieldWidget(field, XtagsWidget(request))

plone.memoize.view.memoize caches the result in the request annotations.
After the request is over your cached result vanishes.

Is it a viable option to store in the object annotations the results of the transform everytime you edit that field?

Another option is to do that the first time the transform is computed, like it is happening for the image scales: the first time you look for an image scale, the original image is scaled and the result is stored in the object annotations.

With something similar (some time ago), I used two fields for the behavior ( tags and 'body_text' and the rendered/transformed html was copied to the body_text field on each save.

I considered this a hack (maybe it is not ?)

The easies way is probably to write a view for a content type, but I tried to learn something new :slight_smile:

I will test both approaches.

Thanks for you help

1 Like