Search code examples
flaskbrython

How can I pass JSON data through serialization and then parse them using external Brython script?


The attached Flask+Brython source code was supposed to print 20 random numbers (between -100 and 100) on the browser screen.

However, it doesn't.

The Brython script is failing to parse JSON data.

How can I fix this?

enter image description here

app.py

from flask import Flask, render_template
from flask import request, redirect
from flask_socketio import SocketIO, emit

async_mode = None
app = Flask(__name__)
socketio_obj = SocketIO(app)


@app.route('/', methods=['GET', 'POST'])
def index():
    import random
    import json
    random_list = []
    for i in range(0, 20):
        n = random.randint(-100, 100)
    random_list.append(n)
    json_data = str(json.dumps(random_list))
    return render_template('index.html', json_data=json_data)


if __name__ == '__main__':
    socketio_obj.run(app, debug=True)

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Brython Test</title>
    <script src="../static/brython/Brython-3.11.1/brython.js"></script>
    <script src="../static/brython/Brython-3.11.1/brython_stdlib.js"></script>
</head>
<body onload="brython()">
    <script type="text/python" src="../static/brython/index.py"></script>
</body>
</html>

index.py

from browser import document, window, console
import os   

random_list = "{{json_data}}"
document <= random_list

Solution

  • Unfortunately you can only use the jinja syntax within a template and not in a loaded file. So you have nothing else to do than integrate the brython code into your template or obtain the data from another endpoint via ajax.

    To pass a variable to brython, you can use the jinja filter tojson due to the similarity in syntax. This gives you the list of numbers and you can attach them to the document.

    Flask (./app.py)
    @app.route('/')
    def index():
        random_list = [random.randint(-100, 100) for _ in range(20)]
        return render_template('index.html', **locals())
    
    Brython (./index.html)
    from browser import document
    
    random_list = {{ random_list | tojson }}
    document <= ','.join(str(item) for item in random_list)
    

    If you want to get the data via Ajax, the following variant is possible.

    Flask (./app.py)
    from flask import jsonify
    import random 
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    @app.route('/data')
    def data():
        random_list = [random.randint(-100, 100) for _ in range(20)]
        return jsonify(random_list)
    
    Brython (./static/brython/index.py)
    from browser import ajax, document
    
    read = lambda req: document <= ','.join(str(n) for n in req.json)
    ajax.get("/data", mode="json", oncomplete=read)