Search code examples
python-3.xdjangowagtailwagtail-streamfield

Wagtail - pass parameters to struct block


I'm trying to pass parameters to a struct block, which also has child struct blocks to load the choices dynamically through choice block. Tried the concept with init method, but no success yet. Below is my implementation code -

class DefaultThemeTemplate(blocks.StructBlock):
    template = blocks.ChoiceBlock(choices=[], label=_('Select a template'), required=False)

    def __init__(self, folder=None, **kwargs):
        self.template = blocks.ChoiceBlock(choices=get_designs(folder), label=_('Select a template'),
                                           required=False)
        super(DefaultThemeTemplate, self).__init__(**kwargs)

    class Meta:
        label = _('Default Theme')
        
        
class ThemeOneTemplate(blocks.StructBlock):
    template = blocks.ChoiceBlock(choices=[], label=_('Select a template'), required=False)

    def __init__(self, folder=None, **kwargs):
        self.template = blocks.ChoiceBlock(choices=get_designs(folder), label=_('Select a template'),
                                           required=False)
        super(ThemeOneTemplate, self).__init__(**kwargs)

    class Meta:
        label = _('Theme One')
        
        
class ThemeTwoTemplate(blocks.StructBlock):
    template = blocks.ChoiceBlock(choices=[], label=_('Select a template'), required=False)

    def __init__(self, folder=None, **kwargs):
        self.template = blocks.ChoiceBlock(choices=get_designs(folder), label=_('Select a template'),
                                           required=False)
        super(ThemeTwoTemplate, self).__init__(**kwargs)

    class Meta:
        label = _('Theme Two')


class Templates(blocks.StructBlock):
    default_theme = DefaultThemeTemplate(folder='', required=False)
    theme_one = ThemeOneTemplate(folder='', required=False)
    theme_two = ThemeTwoTemplate(folder='', required=False)

    def __init__(self, folder=None, **kwargs):
        self.default_theme = DefaultThemeTemplate(folder=folder, required=False)
        self.theme_one = ThemeOneTemplate(folder=folder, required=False)
        self.theme_two = ThemeTwoTemplate(folder=folder, required=False)
        super(Templates, self).__init__(**kwargs)

    class Meta:
        label = _('Template')
        
        
class StaticPage(Page):
    template = StreamField([
        ('template', Templates(required=False, folder='pages'))
    ], null=True, blank=True, verbose_name=_('Template'))

Here's the screenshot with the blank choice fields -

enter image description here

Please help me find out what am I doing wrong here. Thanks in advance.


Solution

  • If you're modifying child blocks inside an __init__ method, you'll need to call super() first and then set the entry in the self.child_blocks dict. Setting self.template won't work because the code that processes all the named attributes and turns them into a list of child blocks has already run at that point, at class definition time.

    In addition, you'll probably need to call set_name('template') on the block you create. So, something like:

    def __init__(self, folder=None, **kwargs):
        super().__init__(**kwargs)
        template_block = blocks.ChoiceBlock(choices=get_designs(folder), label=_('Select a template'), required=False)
        template_block.set_name('template')
        self.child_blocks['template'] = template_block