如何将数据列表从烧瓶传递到 JS?

How to pass lists of data from flask to JS?

我的 python Flask 服务器中有一组列表,即 c_datadatatargetxtargetysizexsizey。它们看起来像下面这样:

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]

c_data在js文件中声明为canvas_data = {"pencil": [], "line": [], "rectangle": [], "circle": [], "eraser": [], "last_action": [] };,这可能有助于你更好地理解c_data的结构)

如何传递这些列表以便我可以在 JS 中再次阅读它们?

这是我的尝试,在 app.py 文件中,我首先执行以下操作将数据发送到脚本:

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})

我通过渲染 HTML 将它传递给 Jinja,我在 JavaScript 中也有一个名为 pencil() 的函数,我使用它尝试了这样的事情:

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

并且在我的 script.js 中,我通过以下方式使用传递的数据来读取它们:

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();
}

使用这种方法,所有数据都工作正常 除了 c_data,它没有转换为我期望的 canvas_data 对象类型并且它的字符串中有一些反斜杠。当我尝试使用 c_data = c_data.replace(/\/g, ''); 行删除反斜杠时,出现错误:

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

如何将上述数据类型正确解析为JS并读取?

从您的解释中推断出您的代码有点困难。

如果在服务器端省略json.dumps,就不用在浏览器中再次解析数据了。这消除了当时不必要的 JSON.parse.

调用

可以通过多种方式将数据从 Flask 传递到 JavaScript。

1) 使用 tojson 过滤器:

一种可能是像往常一样将数据传输到模板,然后使用 Jinja 过滤器 tojson.

将其转换为 JSON
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) 获取使用jsonify转换的数据:

另一种可能性是通过AJAX从另一个端点获取数据。服务器端使用jsonify.

将数据转换成JSON格式
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>