2016-11-14 78 views
3

是否可以使用每个插件扩展ControlPanel-View?延长Plone-Controlpanel表格

对于实施例
ca.db.core - >使对于DB连接设置基本字段集/标签
ca.db.person - >如果安装,增加了 “核心” 设置的新字段集/标签的人的特定字段/设置
ca.db.schema - >如果安装了,还增加了对schema.org领域的新字段集/标签

回答

3

是的,它是可能的,我曾经讨论过这个问题,一个人,他写了bda.plone.shop插件。

他们面临同样的问题,并通过使用ContextProxy对象来解决它,它将不同的模式定义放在一个代理对象中。

使用代理是恕我直言hack,但我不知道更好的解决方案。

代理尝试从模式列表中获取/设置属性。 请注意,您需要处理冲突的名称,这意味着如果您在多个模式中具有相同的字段名称。

class ContextProxy(object): 

    def __init__(self, interfaces): 
     self.__interfaces = interfaces 
     alsoProvides(self, *interfaces) 

    def __setattr__(self, name, value): 
     if name.startswith('__') or name.startswith('_ContextProxy__'): 
      return object.__setattr__(self, name, value) 

     registry = getUtility(IRegistry) 
     for interface in self.__interfaces: 
      proxy = registry.forInterface(interface) 
      try: 
       getattr(proxy, name) 
      except AttributeError: 
       pass 
      else: 
       return setattr(proxy, name, value) 
     raise AttributeError(name) 

    def __getattr__(self, name): 
     if name.startswith('__') or name.startswith('_ContextProxy__'): 
      return object.__getattr__(self, name) 

     registry = getUtility(IRegistry) 
     for interface in self.__interfaces: 
      proxy = registry.forInterface(interface) 
      try: 
       return getattr(proxy, name) 
      except AttributeError: 
       pass 

     raise AttributeError(name) 

现在,您需要使用代理在ControlPanel控制形式。 我假设你正在使用的RegistryEditFormplone.registry

class SettingsEditForm(controlpanel.RegistryEditForm): 
    schema = ISettings 
    label = _(u"Settings") 
    description = _(u"") 

    # IMPORTANT Note 1 - This is where you hook in your proxy  
    def getContent(self): 
     interfaces = [self.schema] # Base schema from ca.db.core 
     interfaces.extend(self.additionalSchemata) # List of additional schemas 
     return ContextProxy(interfaces) 

    # IMPORTANT Note 2 - You may get the additional schemas dynamically to extend the Settings Form. For example by name (startswith...) 
    # In this case they have a separate interface, which marks the relevant interfaces. 
    @property 
    def additionalSchemata(self): 
     registry = getUtility(IRegistry) 
     interface_names = set(record.interfaceName for record 
           in registry.records.values()) 

     for name in interface_names: 
      if not name: 
       continue 

      interface = None 
      try: 
       interface = resolve(name) 
      except ImportError: 
       # In case of leftover registry entries of uninstalled Products 
       continue 

      if ISettingsProvider.providedBy(interface): 
       yield interface 

    ... 

你可以找到完整的代码here