Created
September 22, 2024 19:02
-
-
Save cnk/d85104c348f727b6b4f9927c7614a844 to your computer and use it in GitHub Desktop.
StructBlock enforcing minimum size for images
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
class MixedMediaBlock(blocks.StructBlock): | |
""" | |
A Block which can display an Image and/or a Video. | |
""" | |
def __init__(self, local_blocks=None, **kwargs): # noqa | |
super().__init__(**kwargs) | |
self.min_width = kwargs.get('min_width', None) | |
self.min_height = kwargs.get('min_height', None) | |
image = ImageChooserBlock(required=False) | |
video = EmbedBlock( | |
label="Video URL", | |
help_text="Paste the video URL from YouTube or Vimeo." | |
" e.g. https://www.youtube.com/watch?v=ox6GYTnWVnM or https://vimeo.com/207076450.", | |
required=False | |
) | |
caption = blocks.CharBlock( | |
required=False, | |
help_text="Adds a caption to the Video, or overrides any caption on the Image." | |
) | |
link = LinkBlock() # LinkBlock allows page, document, or external link. | |
def clean(self, value): | |
result = [] | |
errors = {} | |
for name, val in value.items(): | |
try: | |
result.append((name, self.child_blocks[name].clean(val))) | |
except ValidationError as e: | |
errors[name] = ErrorList([e]) | |
# If we have size restrictions, check if this image (if it exists) is big enough | |
if self.min_width and self.min_width and name == 'image' and val: | |
if val.width < self.min_width or val.height < self.min_height: | |
errors['image'] = ErrorList([ | |
f"Images must be at least {self.min_width} x {self.min_height}; " + | |
f"this image is {val.width} x {val.height}" | |
]) | |
if value['image'] and value['video']: | |
errors['image'] = ErrorList(["You must provide either an image or a video url but not both."]) | |
if not value['image'] and not value['video']: | |
errors['image'] = ErrorList(["You must provide either an image or a video url for each item."]) | |
if errors: | |
raise StructBlockValidationError(block_errors=errors) | |
return self._to_struct_value(result) | |
# And then a carousel block that uses MixedMediaBlock and requires minimum size | |
class CenteredImageCarouselBlock(blocks.StructBlock): | |
images = blocks.ListBlock( | |
MixedMediaBlock(min_width=770, min_height=450), | |
label="Media Assets" | |
) | |
randomize = blocks.BooleanBlock( | |
required=False, | |
default=False, | |
help_text="Randomize order in which the images are displayed.", | |
) | |
def get_context(self, value, parent_context=None): | |
context = super().get_context(value, parent_context) | |
if value['randomize']: | |
shuffle(value['images']) | |
class Meta: | |
label = 'Centered Image Carousel' | |
template = 'namespace/blocks/centered-image-carousel-block.html' | |
form_classname = 'centered-image-carousel-block struct-block' | |
icon = 'image' | |
group = 'Multimedia' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment