How to use annotations with z3c.form DictionaryField

There is documentation on using Python dict with z3c.form(loading and saving form data).

However z3c.form datamanager, the one used for dicts is not registered for other types or interfaces (see link ), while usually annotations use something like PersistentDict.

How can I use DictionaryField datamanagerin this scenario? I.e. so in my method getContentI just return the annotation PersistentDict.

+4
source share
2 answers

Well, unfortunately, there is no easy solution for this requirement. I once encountered the same problem using a datagrid field in the form of z3c.

The following statement solves the problem for the datagrid field, which is list(PersistentList from dicts(PersistentMappings).

I think you can adapt this solution for your business.

First you need to add the following code to the method getContent:

from plone.directives import form

class MyForm(form.SchemaEditForm):

    schema = IMyFormSchema
    ignoreContext = False

    def getContent(self):
        annotations = IAnnotations(self.context)
        if ANNOTATION_KEY not in annotations:
            annotations[ANNOTATION_KEY] = PersistentMapping()
        return YourStorageConfig(annotations[ANNOTATION_KEY])

Important Note. . I am moving the annotation repository to suit the get / set behavior of the z3c form. Check out the following implementation YourStorageConfigand you will see why :-).

class YourStorageConfig(object):
    implements(IMyFormSchema)

    def __init__(self, storage):
        self.storage = storage

    def __getattr__(self, name):
        if name == 'storage':
            return object.__getattr__(self, name)
        value = self.storage.get(name)
        return value

    def __setattr__(self, name, value):
        if name == 'storage':
            return object.__setattr__(self, name, value)
        if name == 'yourfieldname':
            self.storage[name] = PersistentList(map(PersistentMapping, value))
            return

        raise AttributeError(name)

yourfieldname must be the name of the field that you use in the form layout.

To implement the datagrid field, you need to do one more work, but this may be enough for your case.

, , . /, -)

+2

, , ZCML:

<adapter
  for="persistent.dict.PersistentDict zope.schema.interfaces.IField"
  provides="z3c.form.interfaces.IDataManager"
  factory="z3c.form.datamanager.DictionaryField"
 />

(PersistentDict) :

def getContent(self):
   "return the object the form will manipulate (load from & store to)"
   annotations =  IAnnotations(self.context)
   return annotations[SOME_ANNOTATIONS_KEY_HERE]

, a PersistentDict annotations[SOME_ANNOTATIONS_KEY_HERE] - KeyError. , getContent, , , .

, , - z3c.form DictionaryField , PersistentDict , . z3c.form .

+1

Source: https://habr.com/ru/post/1612927/


All Articles