[Solved] Property of custom content not persistent


I wrote a new content type like this:

from plone.dexterity.content import Container
from plone.supermodel import model
from zope.interface import implementer

from plone.namedfile.field import NamedBlobFile

class IZipNode(model.Schema):
    """ Marker interface and Dexterity Python Schema for Buch

    zipFile = NamedBlobFile(
        required = False,
        title = "Zip-File",
        description = "Upload your zip file here."

class ZipNode(Container):
    idMap = {}

In a custom view I do something with that zipFile and fill the property idMap with some information. For some reason the property holds its value on my local development but not on the same installation with the same code on my server. Sometimes the new value is there but most of the time the value is just an empty dictionary again.

What am I doing wrong here? Why is idMap sometimes stored persistently and sometimes not?

This is a ZODB limitation: it recognizes only assignments to attributes of persistent objects as indication to persist a change. In your case, you modify idMap (a dict) via dict methods and not via a new assignment.

You have several options:

  • replace the datatype for idMap by a persistent type (e.g. PersistentMapping or OOBTree)
  • after a change to idMap assign it anew (e.g. self.idMap = self.idMap).
  • use self._p_change = True to tell the ZODB that you have changed self.

In all cases, you must ensure that idMap becomes an intance (not a class) attribute.

Thank you, Dieter.

I changed my code to this to make idMap a real instance property.

class ZipNode(Container):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.idMap = {}

And after each change I assign idMap to itself. This seems to work for now.
Are there any performance differences between your suggested solutions?

No significant performance differences -- unless your object has large data besides idMap. In the latter case, it would be more efficient to make idMap its own persistent object; then idMap modifications would not require a modification of the parent object.

There are only a few nested dictionaries with little data, just some short folder and file names.
But it's good to know when to use what.

Usually I use fields for all kind of stuff but in my case that was not necessary, so I decided to use a property. I also will take a look at OOBTree and PersistentMapping to learn more about it.