我有一个Dexterity内容类型,plone.directives.form.Schema其中包含许多用于分配默认值的表单提示:
@form.default_value(field=ITrial['start_on'])
def default_start_on(data):
return datetime.now()
Run Code Online (Sandbox Code Playgroud)
一些默认值更复杂,传回自身为Dexterity类型实例的对象.这些对象对于主要类型的设置至关重要,由各种事件触发.
我现在正在测试.理想情况下,我希望能够使用以下内容:
item = createContentInContainer(folder, 'ctcc.model.trial', 'item')
Run Code Online (Sandbox Code Playgroud)
也就是说,我希望项目可以选择默认值而无需手动传递给构造函数.
如果我正在使用,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)
Run Code Online (Sandbox Code Playgroud)
它仍然感觉我正在复制表单行为的一部分,但至少它使用提供表单默认值的相同功能.
正如您所发现的,@form.default_value 装饰器受到 z3c.form 表单的尊重,但在以其他方式创建项目时则不然。您有多种选择:
为您的内容类型编写一个 ObjectCreatedEvent 处理程序,以设置必要的默认值。这是最简单的实现方法,但如果该事件的其他处理程序需要这些值,则可能不起作用。
创建您自己的 Dexterity 通用 Item 类的子类,并使用它而不是 Item 作为内容类型的基础。然后您可以自定义__init__方法来设置你想要的任何内容。不过,这将需要迁移现有的内容项目(如果您已经有一些内容项目)。
这是一个更复杂的选项。替换用于构造内容类型的工厂实用程序。createContentInContainer 最终会查找名称与内容类型的 FTI 的工厂属性相同的 IFactory 实用程序。默认实现已存在plone.dexterity.factory,但您可以将其替换为具有更多功能的其他实现。