使用 js 或 jquery 在 jinja 语句中使用 json 列表元素

use json list element inside a jinja statement using js or jquery

这是我的代码:

                $("select").change(function(){
                $.post("/sort", {sort:$(this).val()}, function(table_data)
                {
                    for (let i in table_data)
                    {
                        var tr = $("<tr/>");
                        var filename = table_data[i].filename;
                        var size = table_data[i].size;
                        var uploaded = table_data[i].upload_time;
                        tr.append("<td>"+filename+"</td>");
                        tr.append("<td>"+size+"</td>");
                        tr.append("<td>"+uploaded+"</td>");
                        **tr.append("<td>"+"<a href='{{url_for('.download', filename=***filename***)}}'>"+'Download'+"</a>"+"</td>")**;
                        tr.appendTo(table);
                    }

有趣的是,js 语句中的 jinja 语句有效,浏览器指向该路径,但文件名仍然是 None,因为使用 python flask 的服务器无法解析该值从这里发送,这是一个 js 变量。 Table_data 是使用 jsonify 从服务器返回的 json 以响应 ajax 调用。我的问题是是否有任何方法可以在该 jinja 语句中使用 'filename' js 变量,或者将其转换为 jinja 变量。谢谢

正如我在评论中所写,只有在提供页面时才能将变量从 Jinja 传递到 JavaScript。这个时间在 AJAX 请求期间已经过去了。

我认为最好的解决办法是在服务器上用url_for构建url,然后通过JSON与记录一起传输。所以你的要求应该可以满足。

我根据你的问题给你写了一个小例子。
列出应用程序静态文件夹中的所有文件夹,供用户选择。如果他选择了一个目录,则通过Ajax查询文件信息和下载URL。然后信息显示在 table.

烧瓶 (app.py)
import os
from datetime import datetime
from flask import Flask
from flask import (
    jsonify,
    render_template,
    request,
    send_from_directory,
    url_for
)

app = Flask(__name__)

@app.route('/')
def index():
    # List all folders in the static folder.
    folders = [file \
        for file in os.listdir(app.static_folder) \
        if os.path.isdir(os.path.join(app.static_folder, file))
    ]
    return render_template('index.html', **locals())

@app.route('/stats', methods=['POST'])
def stats():
    # Return stats of all files in the selected folder.
    if 'target' in request.form:
        data = []
        target = request.form['target']
        try:
            for filename in os.listdir(os.path.join(app.static_folder, target)):
                filepath = os.path.join(app.static_folder, target, filename)
                data.append(
                    {
                        'filename': filename,
                        'filesize': os.path.getsize(filepath),
                        'filetime': datetime.fromtimestamp(os.path.getmtime(filepath)).isoformat(),
                        'filedest': url_for('.download', filename=os.path.join(target, filename))
                    }
                )
            return jsonify(data)
        except OSError: pass
    return '', 400

@app.route('/download/<path:filename>')
def download(filename):
    return send_from_directory(app.static_folder, filename)
HTML (templates/index.html)
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Index</title>
  </head>
  <body>
    <select name="target">
      <option disabled selected value>-- select an option --</option>
      {% for folder in folders -%}
      <option value="{{folder}}">{{folder}}</option>
      {% endfor -%}
    </select>

    <table id="my-table" style="width: 100%"></table>

    <script
      src="https://code.jquery.com/jquery-3.6.0.min.js"
      integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
      crossorigin="anonymous"></script>

    <script type="text/javascript">
      ((uri) => {
        $(document).ready(function() {
          $('select[name="target"]').change(function(evt) {
            $('table#my-table').empty();
            $.post(uri, { target: $(this).val() })
              .done(function(data) {
                data.forEach(info => {
                  const { filename, filesize, filetime, filedest } = info;
                  const row = $('<tr/>');
                  row.html(`
                    <td>${filename}</td>
                    <td>${filesize}</td>
                    <td>${filetime}</td>
                    <td><a href="${filedest}">Download</a></td>
                  `)
                  row.appendTo($('table#my-table'));
                });
              });
          })
        });
      })({{ url_for('.stats') | tojson }});
    </script>
  </body>
</html>