在以编程方式创建的Dexterity项目上设置字段默认值

时间:2012-08-01 06:27:56

标签: plone dexterity

我有一个基于plone.directives.form.Schema的敏捷内容类型,它有许多用于分配默认值的表单提示:

@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)

感觉我仍然感觉复制了部分表单行为,但至少它使用了提供表单默认值的相同功能。

1 个答案:

答案 0 :(得分:1)

正如您所发现的那样,@ form.default_value装饰器受到z3c.form表单的尊重,但是当以其他方式创建项目时则不会。您有几种选择:

  1. 为您的内容类型编写ObjectCreatedEvent的处理程序,以设置必要的默认值。这是最简单的实现方法,但如果此事件的其他处理程序需要适当的值,则可能无效。

  2. 创建自己的Dexterity通用Item类的子类,并使用它代替Item作为内容类型的基础。然后,您可以自定义__init__方法以设置您想要的任何内容。如果您已经有一些内容项,则需要迁移现有内容项。

  3. 这是一个更复杂的选择。替换用于构造内容类型的工厂实用程序。 createContentInContainer最终会查找名称等于内容类型的FTI的factory属性的IFactory实用程序。默认实现位于plone.dexterity.factory,但您可以将其替换为执行更多操作的其他实现。