Created
April 26, 2018 15:14
-
-
Save gasman/10f826cfa83627d3a17584ad327a78fa to your computer and use it in GitHub Desktop.
Splitting multi-paragraph StreamField blocks into individual blocks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import absolute_import, unicode_literals | |
from bs4 import BeautifulSoup, Tag | |
from django.db import models | |
from wagtail.wagtailadmin.edit_handlers import StreamFieldPanel | |
from wagtail.wagtailcore import blocks | |
from wagtail.wagtailcore.fields import StreamField | |
from wagtail.wagtailcore.models import Page | |
from wagtail.wagtailcore.rich_text import RichText | |
class HomePage(Page): | |
body = StreamField([ | |
('heading', blocks.CharBlock()), | |
('paragraph', blocks.RichTextBlock()), | |
('multi_paragraph_import', blocks.RichTextBlock()), | |
]) | |
content_panels = Page.content_panels + [ | |
StreamFieldPanel('body'), | |
] | |
def clean(self): | |
super().clean() | |
is_replacing_body = False # becomes true if there are multi_paragraph_import blocks to rewrite | |
new_body = [] # a list of (block_type, value, id) tuples | |
for block in self.body: | |
if block.block_type == 'multi_paragraph_import': | |
is_replacing_body = True | |
soup = BeautifulSoup(block.value.source, 'html5lib') | |
# create a paragraph block for each top-level element in the rich text | |
for element in soup.body.children: | |
# ignore whitespace between elements | |
if isinstance(element, str) and not element.strip(): | |
continue | |
# ignore empty paragraphs | |
if isinstance(element, Tag) and element.name == 'p' and not element.text: | |
continue | |
new_body.append( | |
('paragraph', RichText(str(element)), None) | |
) | |
else: | |
# keep all other block types intact | |
new_body.append((block.block_type, block.value, block.id)) | |
if is_replacing_body: | |
# need to construct a StreamValue to write back to body; writing the list back | |
# will fail because StreamField only recognises (block_type, value) tuples, | |
# not (block_type, value, id) | |
body_block = self._meta.get_field('body').stream_block | |
self.body = blocks.StreamValue(body_block, new_body) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment