简体   繁体   中英

How to pass lists of data from flask to JS?

I have a set of lists in my python Flask server, namely c_data , data , targetx , targety , sizex and sizey . They look something like the following:

c_data:  ['{"pencil":[[{"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},{"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},{"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},{"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},{"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},{"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},{"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}]],"line":[],"rectangle":[],"circle":[],"eraser":[],"last_action":[0]}']
data:  ['data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)]
targetx:  [369]
targety:  [252]
sizex:  [100]
sizey:  [100]

(The c_data is declared in the js file as canvas_data = {"pencil": [], "line": [], "rectangle": [], "circle": [], "eraser": [], "last_action": [] }; , this may help you understand the structure of c_data better)

How do I pass these lists so that I can then read them again in JS?

Here's what I tried, in the app.py file, I first did the following to send the data to the scripts:

c_data = json.dumps(c_data)
data = json.dumps(data)
targetx = json.dumps(targetx)
targety = json.dumps(targety)
sizex = json.dumps(sizex)
sizey = json.dumps(sizey)

return jsonify({'result': 'success', 'c_data': c_data, 'data': data, 'targetx': targetx, 'targety': targety, 'sizex': sizex, 'sizey': sizey})

and I pass it to Jinja by rendering HTML, and I also have a function in JavaScript called pencil() , using which I tried something like this:

<body onload="pencil(`{{ c_data }}`, `{{ data }}`, `{{ targetx }}`, `{{ targety }}`, `{{ sizex }}`, `{{ sizey }}`)">

and in my script.js , I used the passed data in the following way to read them:

async function loadImages(c_data, data, targetX, targetY, targetWidth, targetHeight) {
    c_data = c_data.replace(/'/g, '"');
    data = data.replace(/'/g, '"');
    targetX = targetX.replace(/'/g, '"');
    targetY = targetY.replace(/'/g, '"');
    targetWidth = targetWidth.replace(/'/g, '"');
    targetHeight = targetHeight.replace(/'/g, '"');

    c_data = JSON.parse(c_data);
    data = JSON.parse(data);
    targetX = JSON.parse(targetX);
    targetY = JSON.parse(targetY);
    targetWidth = JSON.parse(targetWidth);
    targetHeight = JSON.parse(targetHeight);
    for (var i = 0; i < data.length; i++) {
        var tx = parseInt(targetX[i]);
        var ty = parseInt(targetY[i]);
        var tw = parseInt(targetWidth[i]);
        var th = parseInt(targetHeight[i]);
        var img = {
            src: await loadImage(data[i], i),
            c_data: c_data[i],
            ul: {
                x: tx,
                y: ty
            },
            ur: {
                x: tx + tw,
                y: ty
            },
            ll: {
                x: tx,
                y: ty + th
            },
            lr: {
                x: tx + tw,
                y: ty + th
            }
        };
        images.push(img)
        
    }
    draw_canvas();
}

Using this approach, all the data works fine except c_data , which does not get converted to the canvas_data object type which I was expecting and has some backslashes in its string. And when I try to remove the backslashes using the line c_data = c_data.replace(/\\/g, '');I get the error:

Uncaught (in promise) SyntaxError: Unexpected token p in JSON at position 4

How do I correctly parse the above data types to JS and read them?

It's a little difficult to deduce your code from your explanations.

If you omit json.dumps on the server, you don't have to parse the data again in the browser. This eliminates the then unnecessary calls of JSON.parse .

Data can be passed from Flask to JavaScript in a number of ways.

1) Using the tojson filter:

One possibility is to transfer the data to the template as usual and then convert it to JSON with the Jinja filter tojson .

from flask import (
    Flask,
    render_template
)

app = Flask(__name__)

@app.route('/')
def index():
    c_data = {
        "pencil":[
            [
                {"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},
                {"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},
                {"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},
                {"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},
                {"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},
                {"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},
                {"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}
            ]
        ],
        "line":[],
        "rectangle":[],
        "circle":[],
        "eraser":[],
        "last_action":[0]
    }
    data = 'data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)'
    targetx = [369]
    targety = [252]
    sizex = [100]
    sizey = [100]
    return render_template('index.html', **locals())
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <script type="text/javascript">
      ((cData, data, targetX, targetY, sizeX, sizeY) => {

        function pencil(cData, data, targetX, targetY, sizeX, sizeY) {
          console.log(cData, data, targetX, targetY, sizeX, sizeY);
        }

        window.addEventListener('DOMContentLoaded', () => {
          pencil(cData, data, targetX, targetY, sizeX, sizeY);
        });
        
      })(
        {{ c_data | tojson }},
        {{ data | tojson }},
        {{ targetx | tojson }},
        {{ targety | tojson }},
        {{ sizex | tojson }},
        {{ sizey | tojson }}
      );
    </script>
  </body>
</html>
2) Get data converted with jsonify:

Another possibility is to obtain the data from another endpoint via AJAX. The data is converted into JSON format on the server side using jsonify .

from flask import (
    Flask,
    render_template,
    jsonify
)

app = Flask(__name__)

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

@app.route('/data')
def data():
    c_data = {
        "pencil":[
            [
                {"startx":183,"starty":165,"endx":183,"endy":167,"thick":2,"color":"#000000"},
                {"startx":183,"starty":167,"endx":187,"endy":169,"thick":2,"color":"#000000"},
                {"startx":187,"starty":169,"endx":188,"endy":171,"thick":2,"color":"#000000"},
                {"startx":188,"starty":171,"endx":190,"endy":172,"thick":2,"color":"#000000"},
                {"startx":190,"starty":172,"endx":190,"endy":174,"thick":2,"color":"#000000"},
                {"startx":190,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"},
                {"startx":191,"starty":174,"endx":191,"endy":174,"thick":2,"color":"#000000"}
            ]
        ],
        "line":[],
        "rectangle":[],
        "circle":[],
        "eraser":[],
        "last_action":[0]
    }
    data = 'data:image/png;base64,iVBORw0KG.......(basically a very long string of base64 encoding)'
    targetx = [369]
    targety = [252]
    sizex = [100]
    sizey = [100]
    return jsonify(
        c_data=c_data, 
        data=data, 
        targetx=targetx, targety=targety, 
        sizex=sizex, sizey=sizey
    )
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>

    <script type="text/javascript">
      (async (uri) => {
        
        function pencil(cData, data, targetX, targetY, sizeX, sizeY) {
          console.log(cData, data, targetX, targetY, sizeX, sizeY);
        }

        const dat = await fetch(uri).then(resp => resp.json());
        const { c_data, data, targetx, targety, sizex, sizey } = dat;
        pencil(c_data, data, targetx, targety, sizex, sizey);

      })({{ url_for('data') | tojson }});
    </script>

  </body>
</html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM