在Flask中渲染具有相同文件名的动态更改图像

时间:2018-11-08 06:41:20

标签: python html flask

我具有如下的烧瓶视图功能:

@app.route('/myfunc', methods = ['POST', 'GET'])
def myfunc():
    var = request.form["samplename"]
    selected_ecg=ecg.loc[ecg['Patient ID'].isin([var])]
    selected_ecg = selected_ecg.drop('Patient ID', 1)
    arr = np.array(selected_ecg)
    y = arr.T
    x=np.array(range(1,189))
    plot.plot(x,y)

    #Remove the old file
    os.remove("static\graph.png")
    #Now save the new image file
    plot.savefig("static\graph.png")

    return render_template("outputs.html")

Outputs.html:

<html>
  <head>

  </head>
   <body>
     <h1>Output page</h1>

      <img src="static/graph.png" />

   </body>

</html>

我使用烧瓶视图功能通过outputs.html文件显示图像。这里要注意的是,每次提供的静态图像文件都会根据用户输入不断变化。换句话说,我一直根据用户选择的输入覆盖图像文件。

但是问题是无法提供更改的图像文件。首次渲染的旧图像文件仅在用户的每个新输入中显示。

我已经提到了有关在烧瓶中投放动态内容的旧文章。但是它们都没有用。

2 个答案:

答案 0 :(得分:4)

thebjorn的解决方案有效。我在Stack Overflow上发现了多个帖子,它们提出了相同的解决方案。要查看它们,请在Google上搜索how to not cache imageslink link2 link3

以下是我对您问题的解决方案。这将删除图形文件,并在对 / myfunc 的每个GET请求中使用plot.savefig创建一个新文件。我不确定要在哪个请求上执行此操作。

@app.route('/myfunc', methods = ['POST', 'GET'])
def myfunc():
    var = request.form["samplename"]
    selected_ecg=ecg.loc[ecg['Patient ID'].isin([var])]
    selected_ecg = selected_ecg.drop('Patient ID', 1)
    arr = np.array(selected_ecg)
    y = arr.T
    x=np.array(range(1,189))
    plot.plot(x,y)

    new_graph_name = "graph" + str(time.time()) + ".png"

    for filename in os.listdir('static/'):
        if filename.startswith('graph_'):  # not to remove other images
            os.remove('static/' + filename)

    plot.savefig('static/' + new_graph_name)

    return render_template("outputs.html", graph=new_graph_name)

Outputs.html

<html>
  <head>

  </head>
   <body>
     <h1>Output page</h1>

      <img src="{{ url_for('static', filename=graph) }}" />

   </body>

</html>

答案 1 :(得分:3)

您遇到了缓存问题。静态资源(例如图像)会缓存在服务器和浏览器之间链中的每个点上。这是一件好事。大多数合理的系统都设置为在服务器上至少缓存图像一年(也就是说,如果它们没有在浏览器中缓存)。

要解决此缓存问题,您需要(i)为文件指定新名称,(ii)重新配置Vary标头以指示不应缓存它们,或(iii)添加一个唯一性片段-例如而不是使用static/graph.png,而是添加时间戳记'static/graph.png?v=' + (new Date()).valueOf()或md5哈希值。

更新:Dinko给了您很好的答案(请阅读他提供的链接)。要在服务器端添加缓存清除功能而不创建新文件,您可以计算md5校验和(缺点:您需要读取整个文件):

from hashlib import md5
fname = 'static/graph.png'
with open(fname, 'rb') as fp:
    checksum = md5.new(fp.read()).hexdigest()
fname += "?v" + checksum

或使用最后修改的属性(并非始终可靠):

from hashlib import md5
fname = 'static/graph.png'
modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
fname += "?v" + checksum
只要文件不变,这两种方法都会提供缓存版本。