Python 当服务器上不存在文件时不显示按钮-使用Flask
只有在我的Flask应用程序创建文件后,才能显示下载按钮吗? 使用PHP,它可能是这样的:Python 当服务器上不存在文件时不显示按钮-使用Flask,python,flask,Python,Flask,只有在我的Flask应用程序创建文件后,才能显示下载按钮吗? 使用PHP,它可能是这样的: <style> .hidden{ display:none;} </style> <?php if(!file_exists("path") ){ $class = "hidden" } echo "<button type=\"submit\" onclick=\"window.op
<style>
.hidden{ display:none;}
</style>
<?php
if(!file_exists("path") ){ $class = "hidden" }
echo "<button type=\"submit\" onclick=\"window.open(\'file.txt\')\">Download!</button>";
?>
更新
@furas回复后的完整代码。
代码应该做什么:
创建一个新线程,该线程将写入一个文件。
将使用隐藏的下载按钮呈现模板。
文件已创建
“下载”按钮自动可见,因为现在该文件已存在。
但是,在下面的代码中,该按钮在写入文件后保持隐藏。该按钮仅在创建文件后重新加载页面时显示
app.py
from flask import Flask, render_template
import threading
import time
import os
global exporting_threads
class ExportingThread(threading.Thread):
def run(self):
time.sleep(1)
file = open("file.txt", "w")
file.close()
app = Flask(__name__)
app.debug = True
@app.route('/')
def index():
exporting_threads = ExportingThread()
exporting_threads.start()
return render_template('index.html', file_exist = os.path.isfile('file.txt'))
if __name__ == '__main__':
app.run()
index.html,位于“模板”文件夹中
<!DOCTYPE html>
<html>
<head>
<style>
.hidden{ display:none;}
</style>
</head>
<body>
{% if file_exist %}
<button type="submit" onclick="window.open('file.doc')">Download!</button>
{% else %}
<button type="submit" class="hidden" onclick="window.open('file.doc')">Download!</button>
{% endif %}
</body>
</html>
PHP将代码与HTML混合在一起,造成了很大的混乱。但烧瓶试着把它分开
在渲染模板之前,请检查文件是否存在于代码中,并仅将结果发送到template-ie
return render_string(...., file_exist=os.path.isfile('file.txt'))
和在模板中
{% if file_exist %}
编辑:
文件通常位于子文件夹中,您应该使用
os.path.isfile('subfolder/file.txt')
甚至
os.path.isfile('/full/path/to/file.txt')
编辑:
问题更为复杂。服务器需要更长的时间在分离的线程中创建文件,所以当服务器检查isfile时,该文件还不存在。它需要JavaScript和AJAX,它们将定期向其他函数发送请求,例如/check,并从isfile发送True或False
使用纯JavaScript和XMLHttpRequest的最小工作示例,但您可以尝试使用fetch或使用库jQuery编写它
完全同意你的答案,只是想扩展它-Jinja的哲学是在模板中只允许尽可能少的逻辑。我建议将控制器中的逻辑与给定的路径链接在一起。谢谢您的输入。但是,在创建或删除文件后,按钮不会更新其类。仅在呈现模板时检查一次文件存在性。下面的解决方案更新button类,但也会每2秒创建一个新按钮@app.route'/'def index:def generate_output:while True:yield render_template'index.html',file_exist=os.path.isfile'file.txt'time.sleep2返回响应带_contextgenerate_output的ream_为什么使用生成器?似乎你有非常不寻常的代码。我不知道你们想做什么,但使用普通函数而不使用生成器,它会在每个请求中重新创建模板,并在每个请求中检查文件。最好在问题中显示完整的示例代码,因为它需要完全不同的方法。现在我知道问题出在哪里了-线程需要更长的时间来创建文件,所以当主线程检查isfile时,该文件不存在。您必须在主线程中创建文件-所以它将在isfile之前创建它。或者,您必须使用JavaScript和AJAX定期询问服务器文件是否已经存在。然后使用JavaScript删除页面上的按钮
os.path.isfile('subfolder/file.txt')
os.path.isfile('/full/path/to/file.txt')
from flask import Flask, render_template_string
import threading
import time
import os
# delete only for test code
#if os.path.isfile('file.txt'):
# os.unlink("file.txt")
class ExportingThread(threading.Thread):
def run(self):
time.sleep(5)
file = open("file.txt", "w")
file.close()
app = Flask(__name__)
app.debug = True
@app.route('/')
def index():
exporting_threads = ExportingThread()
exporting_threads.start()
return render_template_string('''<!DOCTYPE html>
<html>
<head>
<style>
.hidden {display:none;}
</style>
</head>
<body>
<button id="button" type="submit" class="hidden" onclick="window.open('file.doc')">Download!</button>
<script>
// ask server if file exists
function check() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
console.log(this.responseText);
if(this.responseText == 'True') {
// show button
document.getElementById("button").classList.remove("hidden");
// stop checking
clearTimeout(timer);
}
}
};
xhttp.open("GET", "/check", true);
xhttp.send();
}
// repeate function `check` every 1000ms (1s)
var timer = setInterval(check, 1000);
</script>
</body>
</html>''')
@app.route('/check')
def check():
return str(os.path.isfile('file.txt'))
if __name__ == '__main__':
app.run()