Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 当服务器上不存在文件时不显示按钮-使用Flask_Python_Flask - Fatal编程技术网

Python 当服务器上不存在文件时不显示按钮-使用Flask

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

只有在我的Flask应用程序创建文件后,才能显示下载按钮吗? 使用PHP,它可能是这样的:

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