Adding embedded video to StreamField in Wagtail

Wagtail's flexible StreamField facilitates many types of content. In this tutorial we will add embedded video.

July 9, 2020, 6:56 a.m.
Themes: Wagtail Streamfield options

Our starting point is a working Wagtail site with a streamfield. To add video to the StreamField block, add the following line to the StreamField field of your page:

('video', InlineVideoBlock()),

and import InlineVideoBlock from blocks.py. We will create this block using StructBlock. Add to your separate blocks.py file (remove double imports if necessary):

from django.utils.translation import gettext_lazy as _
from wagtail.core import blocks
from wagtail.core.blocks import CharBlock
from wagtail.embeds.blocks import EmbedBlock

class InlineVideoBlock(blocks.StructBlock):
    video = EmbedBlock(label=_("Video"))
    caption = CharBlock(required=False, label=_("Caption"))
    float = blocks.ChoiceBlock(
        required=False,
        choices=[('right', _("Right")), ('left', _("Left")), ('center', _("Center"))],
        default='right',
        label=_("Float"),
    )
    size = blocks.ChoiceBlock(
        required=False,
        choices=[('small', _("Small")), ('medium', _("Medium")), ('large', _("Large"))],
        default='small',
        label=_("Size"),
    )

    class Meta:
        icon = 'media'

All human readable strings are translated using gettext_lazy. The EmbedBlock takes care of embedding video. As any block it accepts an argument label. The field float will be used in the template to position the image or video on the right, left or center of the page; the parameter size works the same way. Both are ChoiceBlocks. The icon argument is given the value media, which will display a video icon.

In our template we have the line

{%  include "streamfield.html" %}

so we only need to make sure that this included template can cater video. Although the include_block tag can render video, we want to add some styling to it, so in streamfield.html add (see repository for the full file):

<div class="block-{{ block.block_type }}-{{ block.value.float }} block-{{ block.value.size }}">
     {% include_block block.value.video %}
     {{ block.value.caption }}
</div>

We reference the individual fields of the StructBlocks via the value property; same for the block_type property. Centering a video is done via margin: auto in our CSS file, which creates equal margins on both sides of the video:

.block-video-center {
    display: grid;
    /* margin auto works here because embed adapts to size of container */
    margin: auto;
    overflow: hidden;
    font: italic 12px Georgia, serif;
}

To make video responsive we have to add the following setting:

WAGTAILEMBEDS_RESPONSIVE_HTML = True

plus add the styling that is mentioned there to our CSS file:

.rich-text img {
    max-width: 100%;
    height: auto;
}
.responsive-object {
    position: relative;
}
.responsive-object iframe,
.responsive-object object,
.responsive-object embed {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

Our article page is ready now. Migrate the database to incorporate the model changes. Then go to the article pages in Wagtail's admin and add video to an existing page or create a new one with a video.

If you would like to add code and code blocks to your StreamField, then read on.

Comment on this article (sign in first or confirm by name and email below)