Как расширить панель инструментов

Панель инструментов django CMS предоставляет API, который позволяет вам добавлять, удалять и манипулировать элементами панели инструментов в вашем собственном коде. Это поможет вам интегрировать режим редактирования django CMS в ваше приложение и предоставить вашим пользователям оптимизированный опыт редактирования.

См.также

Создайте файл cms_toolbars.py

Для того чтобы взаимодействовать с API панели инструментов, необходимо создать подкласс CMSToolbar в собственном коде и зарегистрировать его.

Этот класс должен быть создан в файле cms_toolbars.py вашего приложения, где он будет обнаружен автоматически при запуске Django runserver.

Вы также можете использовать CMS_TOOLBARS для управления тем, какие классы панели инструментов загружаются.

Используйте высокоуровневые API панели инструментов

Вы найдете объект toolbar в запросе в ваших представлениях, и у вас может возникнуть соблазн сделать с ним что-нибудь, например:

toolbar = request.toolbar
toolbar.add_modal_button('Do not touch', dangerous_button_url)

- но не стоит, точно так же, как не рекомендуется тыкать пинцетом в электрические розетки только потому, что можно.

Вместо этого вы должны единственно взаимодействовать с панелью инструментов, используя класс CMSToolbar, и класс documented APIs for managing it.

Аналогично, хотя имеется общий метод add_item(), мы предоставляем методы более высокого уровня для работы с конкретными типами элементов, и всегда рекомендуется использовать их вместо этого.

Определите и зарегистрируйте подкласс CMSToolbar

from cms.toolbar_base import CMSToolbar
from cms.toolbar_pool import toolbar_pool

class MyToolbarClass(CMSToolbar):
    [...]

toolbar_pool.register(MyToolbarClass)

Метод cms.toolbar_pool.ToolbarPool.register также может быть использован в качестве декоратора:

@toolbar_pool.register
class MyToolbarClass(CMSToolbar):
    [...]

Наполнение панели инструментов

Для управления тем, что будет отображаться на панели инструментов django CMS, доступны два метода:

  • populate(), который вызывается до того, как будет отрисована остальная часть страницы

  • post_template_populate(), который вызывается после отрисовки шаблона страницы

Последний метод позволяет управлять панелью инструментов на основе содержимого страницы, например, состояния плагинов или заполнителей, но если вам это не нужно, лучше выбрать более простой метод populate().

class MyToolbar(CMSToolbar):

    def populate(self):

        # add items to the toolbar

Теперь вам нужно решить, какие именно элементы будут отображаться на панели инструментов. К ним можно отнести:

  • menus

  • buttons и списки кнопок

  • различные другие элементы панели инструментов

Создание меню панели инструментов

Описанные выше элементы текстовых ссылок можно также добавить в качестве узлов в меню на панели инструментов.

Меню - это экземпляр cms.toolbar.items.Menu. В вашем подклассе CMSToolbar вы можете либо создать меню, либо идентифицировать уже существующее (чтобы, например, добавить в него новые пункты) в методах populate() или post_template_populate(), используя get_or_create_menu().

def populate(self):
    menu = self.toolbar.get_or_create_menu(
        key='polls_cms_integration',
        verbose_name='Polls'
        )

key - уникальный идентификатор меню; verbose_name - то, что будет отображаться в меню. Если вы знаете, что меню уже существует, вы можете получить его с помощью get_menu().

Примечание

Рекомендуется использовать пространство имен вашего key с именем приложения. В противном случае другое приложение может неожиданно вмешаться в ваше меню.

После создания меню вы можете добавлять в него элементы точно так же, как и на панель инструментов. Например:

def populate(self):
    menu = [...]

    menu.add_sideframe_item(
        name='Poll list',
        url=admin_reverse('polls_poll_changelist')
    )

Чтобы добавить разделитель меню

add_break() помещает Break, визуальный разделитель, в список меню, чтобы позволить группировать пункты. Например:

menu.add_break(identifier='settings_section')

Чтобы добавить подменю

Подменю - это меню, которое принадлежит другому меню Menu:

def populate(self):
    menu = [...]

    submenu = menu.get_or_create_menu(
        key='sub_menu_key',
        verbose_name='My sub-menu'
        )

Затем вы можете добавить элементы в подменю таким же образом, как в примерах выше. Обратите внимание, что подменю является экземпляром SubMenu, и само по себе не может иметь других подменю.

Поиск существующих элементов панели инструментов

get_or_create_menu() и get_menu().

Существует ряд методов и полезных констант для получения и манипулирования существующими элементами панели инструментов. Например, чтобы найти (с помощью get_menu()) и переименовать меню Site:

from cms.cms_toolbars import ADMIN_MENU_IDENTIFIER

class ManipulativeToolbar(CMSToolbar):

    def populate(self):

        admin_menu = self.toolbar.get_menu(ADMIN_MENU_IDENTIFIER)

        admin_menu.name = "Site"

get_or_create_menu() с тем же успехом найдет то же самое меню, а также имеет те преимущества, что:

  • он может сам обновлять атрибуты элемента (self.toolbar.get_or_create_menu(ADMIN_MENU_IDENTIFIER, 'Site'))

  • если элемент не существует, он создаст его, а не выдаст ошибку.

find_items() и find_first().

Поиск предметов по их типу:

def populate(self):

    self.toolbar.find_items(item_type=LinkItem)

найдет все LinkItemна панели инструментов (но не, например, в меню на панели инструментов - он не ищет другие элементы на панели инструментов для собственных элементов).

find_items() возвращает список объектов ItemSearchResult; find_first() возвращает первый объект в этом списке. Они имеют схожее поведение, поэтому в примерах здесь будет использоваться только find_items().

Аргумент item_type всегда обязателен, но вы можете уточнить поиск, используя другие их атрибуты, например:

self.toolbar.find_items(Menu, disabled=True))

Обратите внимание, что эти два метода можно использовать и для поиска элементов в классах Menu и SubMenu.

Управление положением элементов на панели инструментов

Методы добавления пунктов меню на панель инструментов принимают необязательный аргумент position, который можно использовать для управления тем, куда будет вставлен пункт.

По умолчанию (position=None) элемент будет вставлен после существующих элементов на том же уровне иерархии (новое подменю станет последним подменю меню, новое меню станет последним меню на панели инструментов и так далее).

Позиция 0 вставляет элемент перед всеми остальными.

Если у вас уже есть объект, его тоже можно использовать в качестве ссылки. Например:

def populate(self):

    link = self.toolbar.add_link_item('Link', url=link_url)
    self.toolbar.add_button('Button', url=button_url, position=link)

добавит новую кнопку перед элементом ссылки.

Наконец, вы можете использовать ItemSearchResult в качестве позиции:

def populate(self):

    self.toolbar.add_link_item('Link', url=link_url)

    link = self.toolbar.find_first(LinkItem)

    self.toolbar.add_button('Button', url=button_url, position=link)

и поскольку ItemSearchResult может быть приведено к целому числу, вы даже можете сделать:

self.toolbar.add_button(„Button“, url=button_url, position=link+1)

Управление тем, как и когда появляется панель инструментов

По умолчанию ваш подкласс CMSToolbar будет активен (т.е. его методы populate будут вызываться) в панели инструментов на каждой странице, когда пользователь is_staff. Однако иногда подкласс CMSToolbar должен появляться на панели инструментов только при посещении страниц, связанных с определенным приложением.

Подкласс CMSToolbar имеет полезный атрибут, который может помочь определить, должна ли панель инструментов быть активирована. is_current_app является True, когда приложение, содержащее класс панели инструментов, совпадает с приложением, обрабатывающим запрос.

Это позволяет, например, активировать его выборочно:

def populate(self):

    if not self.is_current_app:
        return

    [...]

Если класс панели инструментов находится в другом приложении, а не в том, для которого вы хотите, чтобы он был активен, вы можете перечислить все приложения, которые он должен поддерживать при создании класса:

supported_apps = ['some_app']

supported_apps - это кортеж прикладных точечных путей (например: supported_apps = ('whatever.path.app', 'another.path.app').

Атрибут app_path будет содержать имя приложения, обрабатывающего текущий запрос - если app_path находится в supported_apps, то is_current_app будет True.

Изменение существующей панели инструментов

Если вам нужно изменить существующую панель инструментов (например, изменить атрибут или поведение метода), вы можете сделать это, создав ее подкласс, который реализует необходимые изменения, и зарегистрировав его вместо исходного.

Оригинальный класс можно снять с регистрации, используя toolbar_pool.unregister(), как в примере ниже. Также, если вы изначально вызывали класс панели инструментов с помощью CMS_TOOLBARS, вам нужно будет изменить его, чтобы он ссылался на новый класс.

Пример, в котором мы снимаем с регистрации оригинал и регистрируем свой собственный:

from cms.toolbar_pool import toolbar_pool
from third_party_app.cms_toolbar import ThirdPartyToolbar

@toolbar_pool.register
class MyBarToolbar(ThirdPartyToolbar):
    [...]

toolbar_pool.unregister(ThirdPartyToolbar)

Обнаружение изменений URL-адреса объекта

Если вы хотите следить за созданием объектов или редактированием моделей и перенаправлять после их добавления или изменения, добавьте на панель инструментов атрибут watch_models.

Пример:

class PollToolbar(CMSToolbar):

    watch_models = [Poll]

    def populate(self):
        ...

После добавления этой функции каждое изменение экземпляра Poll через боковой фрейм или модальное окно будет вызывать перенаправление на URL экземпляра опроса, который был отредактирован, в соответствии со статусом панели инструментов:

  • в режиме черновик возвращается get_draft_url() (или get_absolute_url(), если первого не существует)

  • в режиме live, и метод существует, возвращается get_public_url().

Frontend

Если вам необходимо взаимодействовать с панелью инструментов или иным образом учитывать ее в коде фронтенда вашего сайта, она предоставляет крючки CSS и JavaScript для использования.

Он добавит различные классы к элементу <html> страницы:

  • cms-ready, когда панель инструментов готова

  • cms-toolbar-expanded, когда панель инструментов полностью развернута

  • cms-toolbar-expanding и cms-toolbar-collapsing во время анимации панели инструментов.

Панель инструментов также запускает событие JavaScript под названием cms-ready в документе. Вы можете прослушать это событие с помощью jQuery:

CMS.$(document).on('cms-ready', function () { ... });
Вернуться на верх