Plone 4:如何在Archetypes内容类型中自定义方法?

时间:2015-03-12 13:35:02

标签: adapter plone archetypes plone-4.x

我在Plone 4.3.3下尝试在我的某个产品中自定义原型内容类型的类方法。

我的产品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 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而不是类。

这些都不起作用,每次都不会执行自定义代码。有人有解决方案吗?

2 个答案:

答案 0 :(得分:5)

您需要的解决方案取决于您希望实现的目标。

但是archetypes.schemaextender是错误的解决方案。 schemaextender用于修改架构,包括:

  • 字段顺序
  • 字段/窗口小部件属性
  • 图式
  • 字段的setter / getter
  • 新字段
  • 覆盖字段

实现自己的adaptera绝对是正确的方法。

首先,您需要为默认行为实现适配器。 其次,您需要调整上下文和请求。请求很重要,因为如果安装了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" />

如果未安装ma_fonction包,您的other现在会调用默认适配器。如果安装了other包,则使用不同的适配器。

答案 1 :(得分:1)

你可以使用的最简单的方法(虽然在政治上不正确!)是 monkey-patching

看一下collective.monkeypatcher,您只需要这样的配置(在您的第三方产品中):

<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
相关问题