Wagtail:如何将模型实例传递给小部件并在模板中访问它

Wagtail: How to pass model instance to a widget and access it in template

我有一个基于 Wagtails Page 模型的模型,我正在为其中一个模型字段分配一个自定义小部件。在呈现管理视图时,是否可以使模型实例在小部件 HTML 模板中可访问?我需要管理视图中的小部件来知道 SimplePage 的小部件属于哪个 ID,即获取 {{ page.id }}.

的值
# models.py
class SimplePage(Page):

    name = RichTextField(blank=True)
    geom = PointField()

    content_panels = Page.content_panels + [
        FieldPanel("name"),
        FieldPanel("geom", widget=LeafletWidgetWithMedia()),
    ] 
# widgets.py
class LeafletWidgetWithMedia(LeafletWidget):
    include_media = True
    template_name = "admin/widget.html"

我知道我可以像这样更新我的小部件的上下文:

# widgets.py
# ...
    def get_context(self, name, value, attrs):
        value = None if value in validators.EMPTY_VALUES else value
        context = super(LeafletWidget, self).get_context(name, value, attrs)
        context.update(self._get_attrs(name, attrs))
        return context

但我不知道如何将我的 SimplePage 实例放入小部件以更新上下文。 (我也尝试了 Wagtails before_edit_page hook w/o 成功。)

此信息可用于编辑处理程序,而不是小部件。您可以使用自定义编辑处理程序,一旦它知道页面实例是什么,它就会重新初始化小部件。像这样:

class LeafletPanel(FieldPanel):

    def on_instance_bound(self):
        self.widget = LeafletWidgetWithMedia(page_instance=self.instance)

on_instance_bound() 在面板绑定到页面对象时调用。请注意,在创建新页面时,不会调用它 - 因此您可能需要在小部件中使用一些逻辑来处理这种情况。

然后您调整 LeafletWidgetWithMedia 以在初始化时接受此 instance 参数,并可以将其从 get_context() 方法传递到上下文中:

class LeafletWidgetWithMedia(LeafletWidget):

    def __init__(self, *args, **kwargs):
        self.instance = kwargs.pop('page_instance', None)
        super().__init__(*args, **kwargs)

    def get_context(self, name, value, attrs):
        # ...
        context['page_instance'] = self.instance
        return context