Да, это возможно, я когда-то обсуждали эту проблему с парнем , который написал аддон bda.plone.shop.
Они столкнулись с той же проблемой и решили ее с помощью объекта ContextProxy, который объединяет различные определения схем в один прокси-объект.
Использование прокси - это ИМХО взломать, но я не знаю лучшего решения.
Прокси-сервер пытается получить/установить атрибут из списка схем. Помните, что вам нужно обрабатывать конфликтующие имена, означает, что у вас есть одно и то же имя поля в нескольких схемах.
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. Я полагаю, вы используете RegistryEditForm
от plone.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