如何在 z3c.form 的 DictionaryField 中使用注释



有关于使用Python dict with z3c.form(加载&存储表单数据)。

然而,用于字典的z3c.form datamanager没有为其他类型或接口注册(参见参考文献),而注释通常使用类似PersistentDict的东西。

该场景下如何使用DictionaryField datamanager ?Ie。因此,在我的形式的getContent方法,我只返回PersistentDict注释。

嗯,不幸的是,似乎没有简单的解决方案来满足这个需求。我曾经在使用z3c形式的数据网格字段时遇到过同样的问题。

下面的指令解决了datagrid字段的问题,该字段是list (PersistentList of dicts (PersistentMappings))。

我想你可以根据你的情况调整这个解决方案。

首先,您需要将以下代码添加到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])

重要提示:我包装了注释存储以满足z3c表单的get/set行为。检查以下YourStorageConfig实现,您将了解原因:-)。

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应该是你在表单模式中使用的字段名。

要实现数据网格字段,还有一些工作要做,但这可能对您的情况足够了。

请发表评论,或追溯,以便我可以提供进一步的帮助。如果有必要,我会添加更多的细节/解释;-)

答案很简单,只需注册下面的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]

这是假设PersistentDict先前存储在annotations[SOME_ANNOTATIONS_KEY_HERE]中,否则上面的代码将导致KeyError。更改上面的getContent可能是一个好主意,这样如果注释还不存在,就用一些默认值创建并初始化它。

最后,请注意,由于某种原因,z3c.form警告不要为每个映射类型启用DictionaryField,因此,例如,为表单存储创建PersistentDict子类可能是明智的,而不是直接使用它。我向z3c提交了一个问题。表格,要求澄清警告。

最新更新