使用 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>
这是我的代码:
$("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>