Flask-Meld, ditch JavaScript frameworks for pure Python joy!

Posted on Fri 04 December 2020 in flask-meld

Introducing a new way to build web applications: Flask-Meld  

Flask-Meld demo

Try the demo yourself

Before we dive in, I would like to give credit where credit is due. This extension was heavily inspired by the following projects and people:

There is something I would like to share with everyone. Having tried just about every JS framework out there, there hasn't been a workflow that I have enjoyed. Until now! Yet here I am, writing a whole lot of JavaScript so that I can write less JavaScript. I am an engineer, after all.

Having never written a Flask extension before, this felt a bit intimidating at first. After looking at how a few other extensions worked, all that was needed was to add a couple of custom tags and import a javascript file. With the help of Django-Unicorn and Laravel Livewire I was able to get a pretty decent understanding of how the whole dataflow worked. A few days later, Flask-Meld was born.

There is not a programming project that I have enjoyed more than working on this extension. I want to show how it works and how it can help you create dynamic web interfaces in pure Python.

  • Less context switching.
  • No need to write JavaScript.
  • More fun!

Flask-Meld utilizes WebSockets and morphdom to create server-rendered HTML and swap out DOM elements without refreshing the page.

The source code shown here can be found at https://github.com/mikeabrahamsen/Flask-Meld-Example.

There are three parts to this:

  1. The Flask application
  2. The Flask-Meld Components
  3. Plain jinja templating

The Flask application

For the sake of example, here is a minimal Flask application to get things running:

from flask import Flask, render_template
from flask_meld import Meld

app = Flask(__name__)
app.config['SECRET_KEY'] = 'big!secret'
socketio = app.socketio

meld = Meld()
meld.init_app(app)


@app.route('/')
def index():
    return render_template("base.html")

if __name__ == '__main__':
    socketio.run(app)

This sets up the application and initializes Flask-Meld.

The base.html file is a simple jinja template that loads the Meld scripts and loads a few components on to the page.

<!DOCTYPE html>
<html>
    <head>
        <title>Flask-Meld Example</title>
    </head>
    <body>
        <div>
        {% block content %}
            <!-- Using a component in your template is easy! -->
            {% meld 'counter' %}
        {% endblock %}
        </div>
        <!-- Add the line below to include the necessary meld scripts-->
        {% meld_scripts %}
    </body>
</html>

There are only a couple things worth noting here. The {% meld_scripts %} and {% meld 'counter' %}.

{% meld_scripts %} - This initializes the meld javascript file so that components work.

{% meld 'counter' %} - This is how you add a component to a page. This is much like using {% include 'counter.html' %} but with the difference being that it looks for template named counter.html in templates/meld and subsequently tells Flask-Meld to look for a file named counter.py in meld/components to power the component.

Components

Files placed in meld/components define the data model and functions that the templates will use.

Components are simple Python classes.

The counter component:

# app/meld/components/counter.py

from flask_meld.component import Component


class Counter(Component):
    count = 0

    def add(self):
        self.count = int(self.count) + 1

    def subtract(self):
        self.count = int(self.count) - 1

Templates

Create a file within the templates/meld directory, include {% meld 'component_name' %} where you want the component to load.

<!-- templates/meld/counter.html -->
<div>
    <button meld:click="subtract">-</button>
    <input type="text" meld:model="count" readonly></input>
    <button meld:click="add">+</button>
</div>

The buttons use meld:click to call the add or subtract function of the Counter component. The input uses meld:model to bind the input to the count property on the Counter component.

Pretty simple right? You can use this to create dynamic user interfaces using pure Python and HTML. This is just the beginning. Form handling and validation coming soon!

Reach out on Twitter @mikeabrahamsen and let me know what you think. Feedback appreciated!

Check out Flask-Meld on GitHub

Subscribe to stay up to date with Flask-Meld!

Powered by EmailOctopus