Расширить форму Plone-Controlpanel

Можно ли расширить Controlpanel-View с каждым аддоном?

Например
ca.db.core -> Создает базовый набор полей/вкладку для настроек подключения к БД
ca.db.person -> Если установлено, добавляет в «основные» настройки: новый набор полей/вкладка для конкретных полей/настроек пользователя
ca.db.schema -> Если установлено, также добавляется новый набор полей/вкладка для полей schema.org


person user966660    schedule 14.11.2016    source источник


Ответы (1)


Да возможно, однажды я обсуждал эту проблему с парнем, который написал аддон 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

     ...

Вы можете найти полный код здесь

person Mathias    schedule 14.11.2016