I have defined a custom StructBlock with a StreamField allowing StructBlock instances, such as follows:
class NavigationPageChooserBlock(wagtail_blocks.StructBlock):
title = wagtail_blocks.CharBlock()
page = wagtail_blocks.PageChooserBlock()
class NavigationDropdownMenuBlock(wagtail_blocks.StructBlock):
title = wagtail_blocks.CharBlock()
menu_items = wagtail_blocks.StreamBlock(
[
("page", NavigationPageChooserBlock()),
]
)
For full context, the blocks are used as part of a custom NavigationMenuSetting that I need to use in a content importer from a Drupal site.
@register_setting
class NavigationMenuSetting(BaseSiteSetting):
menu_items = StreamField(
[
("drop_down", NavigationDropdownMenuBlock()),
],
use_json_field=True,
)
I'm having a lot of difficulty trying to figure out how to create a NavigationDropdownMenuBlock instance with child menu_items in Python code. I've tried the following, but get an error.
/wagtail/blocks/stream_block.py", line 290, in get_prep_value
return value.get_prep_value()
^^^^^^^^^^^^^^^^^^^^
AttributeError: 'list' object has no attribute 'get_prep_value'
Here is my importer code:
# example_page is created previously
# NavigationDropdownMenuBlock (StructBlock)
example_dropdown = {
"title": "Dropdown Menu",
# StreamBlock
"menu_items": [
(
"page",
# NavigationPageChooserBlock (StructBlock)
{
"title": "Example Page Link",
"page": example_page,
},
),
],
}
navigation_items = [
("drop_down", example_dropdown),
]
navigation_menu = NavigationMenuSetting(
menu_items=navigation_items,
site_id=1,
)
navigation_menu.save()
I've also tried using StreamValue, but can't figure out what to use for the string_block attribute:
navigation_dropdown = NavigationDropdownMenuBlock(
title="Dropdown Menu",
)
navigation_dropdown.menu_items = StreamValue(
stream_block=navigation_dropdown.menu_items.stream_block,
stream_data=[
{
"type": "page",
# StructBlock
"value": {
"title": "Example Page Link",
"page": example_page,
},
},
],
)
stream_block=navigation_dropdown.menu_items.stream_block,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'NavigationDropdownMenuBlock' object has no attribute 'menu_items'
How can I change my import script to properly create the example_dropdown item for the NavigationMenuSetting.menu_items?
Did you see the Wagtail doc on modifying streamfields? https://docs.wagtail.org/en/stable/topics/streamfield.html#modifying-streamfield-data
If you've used BeautifulSoup before, it works a little similarly: create a tag then append/insert at the appropriate place. You can't just add blocks via the raw data as the UID's would be missing from the blocks, Wagtail wouldn't know what to do with them.
You would need to create
NavigationPageChooserBlockinstances for eachNavigationDropdownMenuBlockinstance you need to create, then append those to yourNavigationMenuSetting.menu_itemsfield.Is there a reason for using a Streamfield and not a clusterable model with orderables? This would make your life a lot easier.