Как передать "self" или Page.id в пользовательскую панель администратора в Wagtail CMS?

В более общем смысле я хочу добавить пользовательскую админку Panel для списка некоторого связанного контента. Для поиска этого связанного содержимого мне нужно передать текущий экземпляр модели или, по крайней мере, ее ID в эту панель. Как я могу это сделать внутри этих списков, в которых отмечены эти панели администратора?

Вот мой конкретный пример ArtistPage. В редакторе я хотел бы добавить панель для списка WorkPages, которые связаны с этим ArtistPage:

from wagtail.models import Page

class ArtistPage(Page):
# ...
content_panels = [
        # ...
        ListWorksPanel(artist=self),  # This doesn’t work
    ]

Сама панель определяется так, в основном копируется из HelpPanel:

from wagtail.admin.panels import Panel

class ListWorksPanel(Panel):
    def __init__(self, artist="", template="admin/list_works_panel.html", **kwargs,):
        super().__init__(**kwargs)
        self.artist = artist
        self.template = template

    def clone_kwargs(self):
        kwargs = super().clone_kwargs()
        del kwargs["help_text"]
        kwargs.update(
            artist=self.artist,
            template=self.template,
        )
        return kwargs

    class BoundPanel(Panel.BoundPanel):
        def __init__(self, panel, instance, request, form):
            super().__init__(panel, instance, request, form)
            self.template_name = self.panel.template
            self.artist = self.panel.artist

Это скорее общий вопрос по Python, я думаю. Я знаю, как передавать "self" в функциях. Но как это работает здесь с этим классом как элементом списка? Я полагаю, что метод __init__() ArtistPage - это то, что нужно, но я не могу понять, как именно.

Каким питоническим способом можно передать "self" другому классу?

Экземпляр ArtistPage передается в BoundPanel.__init__ как аргумент ключевого слова instance. Весь код, имеющий дело с отдельной ArtistPage, должен быть написан внутри класса BoundPanel.

Когда вы пишете ListWorksPanel() как часть определения content_panels, вы создаете экземпляр ListWorksPanel, который затем становится частью определения класса ArtistPage . В этот момент в коде не существует реального экземпляра ArtistPage, поэтому нет self, на который можно было бы сослаться. Фактически, существует единственный объект ListWorksPanel, общий для всех экземпляров ArtistPage, которые когда-либо будут созданы.

Когда приходит время отобразить форму редактирования для отдельной страницы, Wagtail вызывает get_bound_panel объект ListWorksPanel, передавая экземпляр страницы вместе с объектами формы и запроса. ( Полный процесс объясняется здесь.) Это возвращает экземпляр BoundPanel, который является компонентом шаблона, выполняющим окончательный рендеринг. В этом случае вы, вероятно, захотите определить метод get_context_data на BoundPanel, который делает что-то вроде context['works'] = self.instance.works.all() - это сделает переменную works доступной на шаблоне.

Вернуться на верх