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

风流意气都作罢 提交于 2021-01-28 18:43:10

问题


I have a model based on Wagtails Page model and I am assigning a custom widget to one of the models fields. Is it possible to make the model instance accessible in the widgets HTML-template when rendering the admin view? I need the widget in the admin view to know which ID the SimplePage has the widget belongs to, i.e. get the value of {{ 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"

I know I can update the context of my widget like so:

# 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

But I can't figure how to get my SimplePage instance into the widget to update the context. (I also tried Wagtails before_edit_page hook w/o success.)


回答1:


This information is available to the edit handler, not the widget. You could use a custom edit handler which re-initialises the widget once it knows what the page instance is. Something like this:

class LeafletPanel(FieldPanel):

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

on_instance_bound() is called when the panel is bound to a page object. Note that when creating a new page, this will not get called - so you may need some logic in the widget to handle that case.

You then adjust your LeafletWidgetWithMedia to accept this instance argument at initalisation, and can pass that into the context from the get_context() method:

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.page_instance
        return context


来源:https://stackoverflow.com/questions/59894242/wagtail-how-to-pass-model-instance-to-a-widget-and-access-it-in-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!