Dynamic Blocks with StreamField: How I Built an Online Store with Django

As a developer, I always strive to find ways to make my projects more friendly and customizable for the end user. Recently, I created an online store called passionbox.cz for my partner using Django. In this blog post, I'll share how I used StreamField, a library that allows the creation of dynamic blocks on the page, to create a flexible and easy-to-manage interface for the store.

StreamField: What and Why?

StreamField is a library that provides a growable value of elements that can be of different types, making it possible to create dynamic content blocks on the page. It was inspired by the StreamField in Wagtail CMS, and like Wagtail, stores block data in a JSONField. The library is designed to integrate seamlessly with the Django admin interface, making it easy to manage the site's content from the backend.

Implementing StreamField in the Product and Page Models

To implement StreamField in the Product and Page models, I started by defining the different block types I wanted to use. In the Product model, I created a DetailsBlock class, which includes a title, description, images, and corresponding descriptions for each image.

class DetailsBlock(blocks.StructBlock):
    title = blocks.RawHTMLBlock()
    description = blocks.RawHTMLBlock()
    image1 = blocks.TextBlock()
    description1 = blocks.RawHTMLBlock()
    image2 = blocks.TextBlock()
    description2 = blocks.RawHTMLBlock()

I then added a StreamField to the Product model, specifying the DetailsBlock as a block type.

class Product(models.Model):
    ...
    blocks = StreamField(
        block_types=[
            ("details", DetailsBlock()),
        ],
        verbose_name="Product block",
        default=list,
        blank=True,
    )

For the Page model, I created several block types, such as AccordionBlock, CallToActionBlock, and ProductTestimonialBlock. Each block type consists of different content elements, such as questions and answers, button text and links, testimonials, and images.

class AccordionItemBlock(blocks.StructBlock):
    question = blocks.CharBlock()
    answer = blocks.RawHTMLBlock()

class AccordionBlock(blocks.StructBlock):
    items = blocks.ListBlock(AccordionItemBlock)

class CallToActionBlock(blocks.StructBlock):
    title = blocks.RawHTMLBlock()
    description = blocks.RawHTMLBlock()
    button_text = blocks.TextBlock()
    button_link = blocks.RelURLBlock()

class ProductTestimonialBlock(blocks.StructBlock):
    title = blocks.RawHTMLBlock()
    testimonial = blocks.RawHTMLBlock()
    image = blocks.TextBlock()
    button_link = blocks.RelURLBlock()
    items = blocks.ListBlock(blocks.TextBlock())

After defining the block types, I added a StreamField to the Page model, making these block types available for use on the site.

class Page(models.Model):
    ...
    blocks = StreamField(
        block_types=[
            ("accordion", AccordionBlock()),
            ("cta", CallToActionBlock()),
            ("product_testimonial", ProductTestimonialBlock()),
            ("raw_html", blocks.RawHTMLBlock()),
        ],
        verbose_name="Page block",
        default=list,
        blank=True,
    )

Result: A Flexible and Easy-to-Manage Online Store

By implementing StreamField in the Product and Page models, I was able to create an online store that is not only dynamic but also easy to manage through the Django admin interface. The different block types allow my partner to customize the content and layout of the store, tailoring it to the specific needs of the business without requiring any coding knowledge.

The use of StreamField has also made it easier to maintain the site's content and structure, as it provides a clear separation between the different content elements. This modular approach allows for more efficient updates and modifications, as my partner can edit or rearrange the blocks without affecting the rest of the page.

Moreover, StreamField's ability to store block data in a JSONField makes it simple to work with the data programmatically. This flexibility opens up possibilities for further customization and automation, such as generating dynamic meta tags or performing advanced filtering based on block content.

Conclusion

In conclusion, StreamField has proven to be a valuable addition to the passionbox.cz project, enabling the creation of a dynamic and easy-to-manage online store using Django. By implementing various block types in the Product and Page models, I've provided my partner with a flexible and user-friendly interface to manage the site's content and layout.

If you're looking to build a customizable and dynamic website or application, I highly recommend giving StreamField a try. Its seamless integration with Django admin and flexible content management capabilities make it a powerful tool for both developers and non-technical users alike.