Skip to content

Instantly share code, notes, and snippets.

@cnk
Created September 22, 2024 19:02
Show Gist options
  • Save cnk/d85104c348f727b6b4f9927c7614a844 to your computer and use it in GitHub Desktop.
Save cnk/d85104c348f727b6b4f9927c7614a844 to your computer and use it in GitHub Desktop.
StructBlock enforcing minimum size for images
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