
    
        
        
        
            
{"version":"https:\/\/jsonfeed.org\/version\/1","title":"mathspp.com feed","home_page_url":"https:\/\/mathspp.com\/blog\/tags\/flask","feed_url":"https:\/\/mathspp.com\/blog\/tags\/flask.json","description":"Stay up-to-date with the articles on mathematics and programming that get published to mathspp.com.","author":{"name":"Rodrigo Gir\u00e3o Serr\u00e3o"},"items":[{"title":"Streaming data from Flask to HTMX using Server-Side Events (SSE)","date_published":"2023-03-23T00:00:00+01:00","id":"https:\/\/mathspp.com\/blog\/streaming-data-from-flask-to-htmx-using-server-side-events","url":"https:\/\/mathspp.com\/blog\/streaming-data-from-flask-to-htmx-using-server-side-events","content_html":"<p>This short reference article shows how to stream data from a Flask web app to HTMX using server-side events (SSE).<\/p>\n\n<p><img alt=\"\" src=\"\/images\/6\/6\/e\/2\/3\/66e235c3d20efa9b095321369d9b8d05136d760a-thumbnail.webp\"><\/p>\n<h2 id=\"introduction\">Introduction<a href=\"#introduction\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>I have been trying to create a web app with <a href=\"https:\/\/flask.palletsprojects.com\/en\/2.2.x\/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Flask<\/a> and <a href=\"https:\/\/htmx.org\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">HTMX<\/a> that updates the page periodically with data streamed from the Flask backend.\nThe <a href=\"https:\/\/flask.palletsprojects.com\/en\/2.1.x\/patterns\/streaming\/#basic-usage\" target=\"_blank\" rel=\"nofollow noopener noreferrer\" class=\"external-link no-image\">Flask documentation suggests that this should be possible<\/a> if the response wraps a generator function and they show this example:<\/p>\n<pre><code class=\"language-py\">@app.route('\/large.csv')\ndef generate_large_csv():\n    def generate():\n        for row in iter_all_rows():\n            yield f\"{','.join(row)}\\n\"\n    return app.response_class(generate(), mimetype='text\/csv')<\/code><\/pre>\n<p>However, this doesn't work with an HTMX request.<\/p>\n<p>I joined the HTMX Discord and I was told this is because HTMX buffers the complete response.<\/p>\n<p>So, I went looking for other options and I found server-side events.<\/p>\n<h2 id=\"how-to-stream-data-from-flask-to-htmx-in-real-time\">How to stream data from Flask to HTMX in real-time<a href=\"#how-to-stream-data-from-flask-to-htmx-in-real-time\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>To be able to stream data back to HTMX and have it update in real-time, the original request needs to connect to SSE with the appropriate HTMX tags.<\/p>\n<p>Then, the Flask backend must return a response with a generator, and the generator itself must return messages that follow the SSE specification.<\/p>\n<p>The following example works with Flask 2.2.3, HTMX 1.8.6, and the SSE extension from HTMX:<\/p>\n<ul><li>\n<code>templates\/index.html<\/code>:<\/li>\n<\/ul><pre><code class=\"language-html\">&lt;!DOCTYPE html5&gt;\n&lt;head&gt;\n    &lt;script src=\"https:\/\/unpkg.com\/htmx.org@1.8.6\"&gt;&lt;\/script&gt;\n    &lt;script src=\"https:\/\/unpkg.com\/htmx.org\/dist\/ext\/sse.js\"&gt;&lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;p&gt;Here.&lt;\/p&gt;\n    &lt;div hx-ext=\"sse\" sse-connect=\"\/connect\" sse-swap=\"message\"&gt;\n        Contents of this box will be updated in real time\n        with every SSE message received from the chatroom.\n    &lt;\/div&gt;\n    &lt;button hx-post=\"\/pong\" hx-swap=\"outerHTML\"&gt;Pong&lt;\/button&gt;\n&lt;\/body&gt;<\/code><\/pre>\n<ul><li>\n<code>main.py<\/code>:<\/li>\n<\/ul><pre><code class=\"language-py\">import itertools\nimport time\n\nfrom flask import Flask, render_template, Response\n\napp = Flask(__name__)\n\n@app.route(\"\/\")\ndef index():\n    return render_template(\"index.html\")\n\n@app.route(\"\/connect\")\ndef publish_hello():\n    def stream():\n        for idx in itertools.count():\n            msg = f\"data: &lt;p&gt;This is {idx}.&lt;\/p&gt;\\n\\n\"\n            yield msg\n            time.sleep(1)\n\n    return Response(stream(), mimetype=\"text\/event-stream\")\n\n@app.post(\"\/ping\")\ndef route_clicked():\n    return \"\"\"&lt;button hx-post=\"\/pong\" hx-swap=\"outerHTML\"&gt;Pong&lt;\/button&gt;\"\"\"\n\n@app.post(\"\/pong\")\ndef route_pong():\n    return \"\"\"&lt;button hx-post=\"\/ping\" hx-swap=\"outerHTML\"&gt;Ping&lt;\/button&gt;\"\"\"\n\nif __name__ == \"__main__\":\n    app.run(debug=True)<\/code><\/pre>\n<p>If you run your Flask app and open it in your browser, you should see something like this:<\/p>\n<figure class=\"image-caption\"><img title=\"HTMX web page that updates with real-time data from Flask.\" alt=\"Screenshot of a simple web page that uses HTMX to fetch data from Flask and that uses server-side events (SSE) to stream data back from Flask.\" src=\"\/user\/pages\/02.blog\/streaming-data-from-flask-to-htmx-using-server-side-events\/_demo_screenshot.webp\"><figcaption class=\"\">HTMX web page that updates with real-time data from Flask.<\/figcaption><\/figure><p>The second paragraph should update every second with an increasing counter.<\/p>\n<p>The button &ldquo;Pong&rdquo; below is to show that the Flask app still works and clicking the Ping \/ Pong buttons should POST a request to Flask that returns the other button.<\/p>\n<h2 id=\"start-streaming-on-request\">Start streaming on request<a href=\"#start-streaming-on-request\" class=\"toc-anchor after\" data-anchor-icon=\"#\" aria-label=\"Anchor\"><\/a><\/h2>\n<p>The example below connects as soon as the page loads but you may want to use SSE to stream data back from a specific request, instead of on page load.<\/p>\n<p>To do that, what you can do is return the HTML that connects to SSE when <em>that<\/em> event is triggered.\nThe example below shows another simple page with a button that says &ldquo;Connect&rdquo;.\nWhen you click that button, we return the HTML that establishes the SSE connection with Flask and then we start streaming the data:<\/p>\n<ul><li>\n<code>index.html<\/code>:<\/li>\n<\/ul><pre><code class=\"language-html\">&lt;!DOCTYPE html5&gt;\n&lt;head&gt;\n    &lt;script src=\"https:\/\/unpkg.com\/htmx.org@1.8.6\"&gt;&lt;\/script&gt;\n    &lt;script src=\"https:\/\/unpkg.com\/htmx.org\/dist\/ext\/sse.js\"&gt;&lt;\/script&gt;\n&lt;\/head&gt;\n&lt;body&gt;\n    &lt;p&gt;Here.&lt;\/p&gt;\n    &lt;button hx-post=\"\/start-connection\" hx-swap=\"outerHTML\"&gt;Connect&lt;\/button&gt;\n    &lt;button hx-post=\"\/pong\" hx-swap=\"outerHTML\"&gt;Pong&lt;\/button&gt;\n&lt;\/body&gt;<\/code><\/pre>\n<ul><li>\n<code>main.py<\/code>:<\/li>\n<\/ul><pre><code class=\"language-py\">import itertools\nimport time\n\nfrom flask import Flask, render_template, Response\n\napp = Flask(__name__)\n\n@app.route(\"\/\")\ndef index():\n    return render_template(\"index.html\")\n\n@app.post(\"\/start-connection\")\ndef start_connection():\n    return \"\"\"&lt;div hx-ext=\"sse\" sse-connect=\"\/connect\" sse-swap=\"message\"&gt;...<\/code><\/pre>","summary":"This short reference article shows how to stream data from a Flask web app to HTMX.","date_modified":"2025-11-22T09:33:35+01:00","tags":["flask","programming","python","web development"],"image":"\/user\/pages\/02.blog\/streaming-data-from-flask-to-htmx-using-server-side-events\/thumbnail.webp"}]}
