menuwagtailsubmenu

PageChooserPanel not showing


I'm learning django and Wagtail and currently looking to use Streamfield for menus and submenus for a personal site. I modified some code I found via a tutorial video and would want to create a basic menu and submenu. All fields show OK in the Wagtail CMS. The problem is that the pagechooserpanel is not showing in the CMS. I'm not sure what's wrong and how to fix it. I'd really appreciate any help with this

class MenuItemBlock(blocks.StructBlock):

    link_title = blocks.CharBlock(
        blank=True,
        null=True,
        max_length=50
    )

    link_url = blocks.CharBlock(
        max_length=500,
        blank=True
    )

    link_page = models.ForeignKey(
        "wagtailcore.Page",
        null=True,
        blank=True,
        on_delete=models.SET_NULL,
        related_name="+",
    )
    
    open_in_new_tab = blocks.BooleanBlock(default=False, blank=True)

    panels = [
        FieldPanel("link_title"),
        FieldPanel("link_url"),
        PageChooserPanel("link_page"),
        FieldPanel("open_in_new_tab"),
    ]

    @property
    def link(self):
        if self.link_page:
            return self.link_page.url
        elif self.link_url:
            return self.link_url
        return '#'

    @property
    def title(self):
        if self.link_page and not self.link_title:
            return self.link_page.title
        elif self.link_title:
            return self.link_title
        return 'Missing Title'

    class Meta:
        icon = 'plus'
        label = 'Menu Item'
        # template = 'menu_item.html'


class SubMenuBlock(blocks.StreamBlock):
    sub_menu_items = MenuItemBlock()

    panels = [
        FieldPanel("sub_menu_items")
    ]

    class Meta:
        icon = 'list-ul'
        label = 'Sub Menu'
        # template = 'sub_menu.html'


@register_snippet
class Menu(ClusterableModel):
    name = models.CharField(max_length=255)
    slug = AutoSlugField(populate_from="name", editable=True)

    menu_items = StreamField([
        ('MenuItem', MenuItemBlock()),
        ('SubMenu', SubMenuBlock()),
    ], blank=True, use_json_field=True)

    panels = [
        MultiFieldPanel([
            FieldPanel("name"),
            FieldPanel("slug"),
        ], heading="Menu"),

        FieldPanel('menu_items', heading='Menu Items')
    ]

    def __str__(self):
        return self.name


Solution

  • ForeignKey is only valid on Django models, not StreamField blocks. Also, panels definitions are not valid on blocks and will be ignored.

    You should use PageChooserBlock instead:

    link_page = blocks.PageChooserBlock(required=False)
    

    Additionally, the keyword arguments blank and null are not valid on CharBlock - the equivalent is required=False. See the StreamField blocks reference in the Wagtail docs.