Jay Boy
Jay Boy

Reputation: 181

Wagtail - how to access StructBlock class attribute inside block

I'm trying to override my block template as described here:

https://github.com/wagtail/wagtail/issues/3857

I added a BooleanBlock inside the class and tried to use that value to change the template but I get an error "no attribute found".

class Features_Block(StructBlock):
    title = CharBlock()
    description = TextBlock(required=False)

    use_other_template = BooleanBlock(default=False, required=False)

    class Meta:
        icon = 'list-ul'

    def get_template(self, context=None):
        if self.use_other_template:
            return 'other_template.html'

        return 'original_template.html'

I have found this thread which might be the answer but I don't understand how to implement it for my case:

https://github.com/wagtail/wagtail/issues/4387

Upvotes: 3

Views: 1807

Answers (2)

gasman
gasman

Reputation: 25237

The get_template method doesn't receive the block's value as a parameter, so there's no reliable way to vary the chosen template according to that value. You might be able to dig around in the calling template's context to retrieve the block value, as in Matt's answer, but this means the internals of Features_Block will be tied to the use of particular variable names in the calling template, which is a bad thing for reusable code.

(Accessing self.use_other_template doesn't work because self, the Features_Block object, doesn't hold on to the block value as a property of itself - it only serves as a translator between different representations. So, it knows how to render a given dictionary of data as HTML, but that dictionary of data is not something that 'belongs' to the Features_Block.)

get_template is called from the block's render method, which does receive the block value, so overriding render will allow you to vary the template based on the block value:

from django.template.loader import render_to_string
from django.utils.safestring import mark_safe

class Features_Block(StructBlock):

    # ...

    def render(self, value, context=None):
        if value['use_other_template']:
            template = 'other_template.html'
        else:
            template = 'original_template.html'

        if context is None:
            new_context = self.get_context(value)
        else:
            new_context = self.get_context(value, parent_context=dict(context))

        return mark_safe(render_to_string(template, new_context))

Upvotes: 4

Matt
Matt

Reputation: 10312

Check the context that's passed to get_template.

class Features_Block(StructBlock):
    title = CharBlock()
    description = TextBlock(required=False)

    use_other_template = BooleanBlock(default=False, required=False)

    class Meta:
        icon = 'list-ul'

    def get_template(self, context=None):
        if context and context['block'].value['use_other_template']:
            return 'other_template.html'

        return 'original_template.html'

Upvotes: 0

Related Questions