我有一个基于 plone.directives.form.Schema 的 Dexterity 内容类型,它具有许多用于分配默认值的表单提示:
@form.default_value(field=ITrial['start_on'])
def default_start_on(data):
return datetime.now()
一些默认值更复杂,传回的对象本身就是 Dexterity 类型的实例。这些对象对于主要类型的设置至关重要,主要类型由各种事件触发。
我现在正在进行测试。理想情况下,我希望能够使用类似的东西:
item = createContentInContainer(folder, 'ctcc.model.trial', 'item')
也就是说,我希望项目能够获取默认值,而不必手动传递到构造函数中。
如果我使用 zope.schema
,我可以使用 FieldProperty 设置架构字段的代理。是否有与 Dexterity 等效的功能,或者可能是通过表单创建插入对象的功能?
解决方案:我最终选择了 David 的选项 #1,拦截 ObjectCreatedEvent
。
@grok.subscribe(ITrial, IObjectCreatedEvent)
def create_trial(trial, event):
if getattr(trial, 'start_on', None) is None:
trial.start_on = default_start_on(None)
它仍然感觉我正在复制表单行为的一部分,但至少它使用提供表单默认值的相同函数。
最佳答案
正如您所发现的,z3c.form 表单尊重 @form.default_value 装饰器,但以其他方式创建项目时则不然。您有多种选择:
为您的内容类型编写一个 ObjectCreatedEvent 处理程序,以设置必要的默认值。这是最简单的实现方法,但如果该事件的其他处理程序需要这些值,则可能不起作用。
创建您自己的 Dexterity 通用 Item 类的子类,并使用它而不是 Item 作为内容类型的基础。然后你可以自定义
__init__
方法来设置你想要的任何内容。不过,这需要迁移现有的内容项(如果您已经有一些内容项)。这是一个更复杂的选项。替换用于构造内容类型的工厂实用程序。 createContentInContainer 最终会查找名称与内容类型的 FTI 的工厂属性相同的 IFactory 实用程序。默认实现位于
plone.dexterity.factory
中,但您可以将其替换为具有更多功能的其他实现。
关于plone - 设置以编程方式创建的敏捷项目的字段默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11753690/