Created
July 17, 2021 00:31
-
-
Save dkirkham/a1fc6d3a04754d5bb816cf97401fd357 to your computer and use it in GitHub Desktop.
This validator checks the amount of text in a RichTextField, by stripping away basic formatting markup. It also incorporates an adjustment for markup that causes line breaks.
This file contains 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 wagtail.core.models import Page | |
from wagtail.core.fields import RichTextField | |
from proj.richtext_validator import RichTextLengthValidator | |
class AuthorPage(Page): | |
biography = RichTextField( | |
max_length=3600, | |
validators=[RichTextLengthValidator(3000, line_length=50)], | |
features=['bold', 'italic', 'link'], | |
blank=False, | |
null=True, | |
help_text="Full rich-text Biography" | |
) |
This file contains 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 django.core.exceptions import ValidationError | |
from django.utils.deconstruct import deconstructible | |
from bs4 import BeautifulSoup | |
@deconstructible | |
class RichTextLengthValidator: | |
"""ImageField dimensions validator.""" | |
def __init__(self, max_length, line_length, tag_weights=None): | |
""" | |
Constructor | |
Args: | |
max_length (int): maximum number of renders chars | |
line_length (int): nominal number of characters in a line | |
""" | |
self.max_length = max_length | |
self.line_length = line_length | |
if tag_weights: | |
self.tag_weights = tag_weights | |
else: | |
self.tag_weights = { | |
'li': line_length // 2, | |
'p': line_length // 2, | |
'br': line_length // 2, | |
} | |
def __call__(self, value): | |
bs_value = BeautifulSoup(value, 'html5lib') | |
length = 0 | |
for string in bs_value.strings: | |
length += len(string) | |
tag_length = 0 | |
for tag in bs_value.find_all(): | |
if tag.name in self.tag_weights: | |
tag_length += self.tag_weights[tag.name] | |
total_weighted_length = length + tag_length | |
if total_weighted_length > self.max_length: | |
raise ValidationError( | |
"Ensure this richtext value is shorter than {} character equivalents (actual characters: {}, from formatting: {})".format( | |
self.max_length, | |
length, | |
tag_length | |
), | |
code='invalid', | |
params={'value': value} | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment