5

I have a Wagtail project with two different Page models that use identical gallery blocks, but in different ways. In one model, I want to use the gallery in a list of other freeform blocks; but in the other model there is only one gallery appearing in a specific place on the page. The galleries are pretty complex, with lots of options like autoadvance that I don’t want to repeat between models, and which aren’t easy to move into a mixin. I can accomplish what I want by adding an extra gallery StreamField to the strict model, like this: (content_panel etc. omitted)

# models.py
from wagtail.models import Page
from wagtail.core.fields import RichTextField, StreamField
from wagtail.images.blocks import ImageChooserBlock
from wagtail.core.blocks import (
    RichTextBlock, 
    StructBlock, 
    StreamBlock,
)

class ImageWithCaptionBlock(StructBlock):
    image = ImageChooserBlock()
    caption = RichTextBlock()


class GalleryBlock(StructBlock):
    # lots of gallery options like “autoadvance”
    items = StreamBlock([
        ('image', ImageWithCaptionBlock()),
        ('video', EmbedBlock()),
    ])    


class FreeFormContentPage(Page):
    body = StreamField([
        ('richtext', RichTextBlock()),
        ('gallery', GalleryBlock()),
    ], use_json_field=True)


class StrictContentPage(Page):
    body = RichTextField()
    gallery = StreamField([
         ('gallery', GalleryBlock()),
    ], use_json_field=True, max_num=1)

This works but it looks a little weird when editing a StrictContentPage!

screenshot of wagtail admin UI showing nested “Gallery” elements

What I’m looking to do is something like this:


class StrictContentPage(Page):
    body = RichTextField()
    gallery = GalleryBlock()

(or the equivalent via tweaking the admin)

… so that the admin experience looks like:

screenshot of Wagtail admin UI showing one “Gallery” element with an imageblock

Thanks in advance for any pointers!

axoplasm
  • 502
  • 2
  • 10

1 Answers1

0

If you still need this, I would approach it with the mindset of creating a variable for the content that's inside the StreamBlock/StreamField.

Consider the following example:

class ImageWithCaptionBlock(StructBlock):
    image = ImageChooserBlock()
    caption = RichTextBlock()

GALLERY_BLOCKS = [
    ('image', ImageWithCaptionBlock()),
    ('video', EmbedBlock()),
]

class GalleryBlock(StructBlock):
    # lots of gallery options like “autoadvance”
    items = StreamBlock(GALLERY_BLOCKS)    

class FreeFormContentPage(Page):
    body = StreamField([
        ('richtext', RichTextBlock()),
        ('gallery', GalleryBlock()),
    ], use_json_field=True)

class StrictContentPage(Page):
    body = RichTextField()
    gallery = StreamField(GALLERY_BLOCKS, use_json_field=True)

This approach will make the UI more readable for the StrictContentPage page version and maintain the same user experience for the FreeFormContentPage version. Plus, you won't need redundant code to change the fields for the different page types.

I hope this will help you out. Have a great day!

Preben
  • 279
  • 5