Plone 4:如何在 Archetypes 内容类型中自定义方法?
Plone 4 : How to customize a method in Archetypes content types?
我已经尝试在 Plone 4.3.3 下,在我的一个产品中自定义原型内容类型的 class 方法。
我有一个产品 bsw.produit_1
,其内容类型 MyContent
定义如下:
class MyContent(base.ATCTContent):
implements(IMyContent)
meta_type = "MyContent"
schema = MyContent`
def ma_fonction(self):
......
return res
我想在另一个产品中修改我的函数 ma_fonction
的代码。我尝试使用适配器并遵循 plone 文档,但没有成功。
我要自定义的class功能:
class CustomClass(object):
""" """
implements(IMyContent)
adapts(IMyContent)
def at_post_payment_script(self, obj_transaction):
""" """
......
# My new code
return res
我声明适配器的 configure.zcml
:
<adapter for="bsw.produit_1.content.mycontent.MyContent"
provides="bsw.produit_1.interfaces.IMyContent"
factory=".customclass.CustomClass" />
在我的 zcml 声明中,我还尝试将 archetypes.schemaextender.interfaces.ISchemaExtender
设为 provides
或将接口 IMyContent
设为 for
而不是 class .
None 这些都有效,每次都不会执行自定义代码。有人对此有解决方案吗?
您需要的解决方案取决于您想要实现的目标。
但是archetypes.schemaextender是错误的解决方案。
schemaextender 用于修改模式,包括:
- 字段顺序
- field/widget 属性
- 图式
- setter/getter 一个字段
- 新领域
- 覆盖字段
实现自己的适配器绝对是正确的做法。
首先您需要为默认行为实现一个适配器。
其次,您需要调整上下文和请求。该请求很重要,因为如果安装了 other
产品,这是定义更具体适配器的一种方式。
Python 默认实现代码 (adapter.py):
from zope.component import adapts
from zope.interface import Interface
from zope.interface import implements
class IBehavior(Interface):
def __init__(context, request)
"""Adapts context and request"""
# ... more ...
class DefaultBehavior(object):
implements(IBehavior)
adapts(IMyContent, Interface) # IMPORTAN two discriminators
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your default implementation goes here.
使用 zcml 注册适配器:
<adapter factory=".adapter.DefaultBehavior" />
您现在可以调用 ma_fonction
中的默认适配器
from zope.component import getMultiAdapter
class MyContent(base.ATCTContent)
def ma_fonction(self):
adapter = getMultiAdapter((self, self.REQUEST), IDefaultBehavior)
return adapter()
现在您可以使用浏览器层在您的 other
产品中实现更具体的适配器。检查文档,how to register a browserlayer
在您的 other
包中,您现在可以注册一个实现相同 IBehavior
接口的适配器,但也可以调整您的浏览器层。
from other.package.interfaces import IOtherPackageLayer
from zope.component import adapts
from zope.interface import implements
class DifferenBehavior(object):
implements(IBehavior)
adapts(IMyContent, IOtherPackageLayer) # IMPORTAN adapt the browserlayer not Interface
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your different implementation goes here.
也用 zcml 注册:
<adapter factory=".adapter.DifferenBehavior" />
如果未安装 other
软件包,您的 ma_fonction
现在会调用默认适配器。如果安装了 other
包,则不同的适配器。
您可以使用的最简单的方法(虽然在政治上不正确!)是monkey-patching。
看看 collective.monkeypatcher,您只需要这样的配置(在您的第 3 方产品中):
<monkey:patch
description=""
class="your.package.MyContent"
original="ma_fonction"
replacement=".monkeys.new_ma_fonction"
/>
然后在您的包中创建一个 monkeys.py
模块,其中包含新方法:
def new_ma_fonction(self):
# do stuff
return res
我已经尝试在 Plone 4.3.3 下,在我的一个产品中自定义原型内容类型的 class 方法。
我有一个产品 bsw.produit_1
,其内容类型 MyContent
定义如下:
class MyContent(base.ATCTContent):
implements(IMyContent)
meta_type = "MyContent"
schema = MyContent`
def ma_fonction(self):
......
return res
我想在另一个产品中修改我的函数 ma_fonction
的代码。我尝试使用适配器并遵循 plone 文档,但没有成功。
我要自定义的class功能:
class CustomClass(object):
""" """
implements(IMyContent)
adapts(IMyContent)
def at_post_payment_script(self, obj_transaction):
""" """
......
# My new code
return res
我声明适配器的 configure.zcml
:
<adapter for="bsw.produit_1.content.mycontent.MyContent"
provides="bsw.produit_1.interfaces.IMyContent"
factory=".customclass.CustomClass" />
在我的 zcml 声明中,我还尝试将 archetypes.schemaextender.interfaces.ISchemaExtender
设为 provides
或将接口 IMyContent
设为 for
而不是 class .
None 这些都有效,每次都不会执行自定义代码。有人对此有解决方案吗?
您需要的解决方案取决于您想要实现的目标。
但是archetypes.schemaextender是错误的解决方案。 schemaextender 用于修改模式,包括:
- 字段顺序
- field/widget 属性
- 图式
- setter/getter 一个字段
- 新领域
- 覆盖字段
实现自己的适配器绝对是正确的做法。
首先您需要为默认行为实现一个适配器。
其次,您需要调整上下文和请求。该请求很重要,因为如果安装了 other
产品,这是定义更具体适配器的一种方式。
Python 默认实现代码 (adapter.py):
from zope.component import adapts
from zope.interface import Interface
from zope.interface import implements
class IBehavior(Interface):
def __init__(context, request)
"""Adapts context and request"""
# ... more ...
class DefaultBehavior(object):
implements(IBehavior)
adapts(IMyContent, Interface) # IMPORTAN two discriminators
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your default implementation goes here.
使用 zcml 注册适配器:
<adapter factory=".adapter.DefaultBehavior" />
您现在可以调用 ma_fonction
from zope.component import getMultiAdapter
class MyContent(base.ATCTContent)
def ma_fonction(self):
adapter = getMultiAdapter((self, self.REQUEST), IDefaultBehavior)
return adapter()
现在您可以使用浏览器层在您的 other
产品中实现更具体的适配器。检查文档,how to register a browserlayer
在您的 other
包中,您现在可以注册一个实现相同 IBehavior
接口的适配器,但也可以调整您的浏览器层。
from other.package.interfaces import IOtherPackageLayer
from zope.component import adapts
from zope.interface import implements
class DifferenBehavior(object):
implements(IBehavior)
adapts(IMyContent, IOtherPackageLayer) # IMPORTAN adapt the browserlayer not Interface
def __init__(self, context, request):
self.context = context
self.request = request
def __call__(self):
# your different implementation goes here.
也用 zcml 注册:
<adapter factory=".adapter.DifferenBehavior" />
如果未安装 other
软件包,您的 ma_fonction
现在会调用默认适配器。如果安装了 other
包,则不同的适配器。
您可以使用的最简单的方法(虽然在政治上不正确!)是monkey-patching。
看看 collective.monkeypatcher,您只需要这样的配置(在您的第 3 方产品中):
<monkey:patch
description=""
class="your.package.MyContent"
original="ma_fonction"
replacement=".monkeys.new_ma_fonction"
/>
然后在您的包中创建一个 monkeys.py
模块,其中包含新方法:
def new_ma_fonction(self):
# do stuff
return res