Render dynamically changing images with same filenames in Flask











up vote
5
down vote

favorite












I have a flask view function as below:



@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("staticgraph.png")
#Now save the new image file
plot.savefig("staticgraph.png")

return render_template("outputs.html")


Outputs.html:



<html>
<head>

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

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

</body>

</html>


I use the flask view function to display an image through the outputs.html file. The catch here is that the static image file that is served keeps changing every time based on user inputs. In other words, I keep overwriting the image file based on the inputs the user has selected.



But the problem is that the changing image file is not served. The old image file that was used for first time render is only displayed for every new input of the user.



I have already referred to old posts regarding serving dynamic content in flask. But none of them served useful.










share|improve this question
























  • The backslashes `` in your paths should probably be escaped..?
    – thebjorn
    Nov 8 at 6:48












  • @thebjorn I have changed the format of that line. Though it doesn't work.
    – Aishu
    Nov 8 at 6:51















up vote
5
down vote

favorite












I have a flask view function as below:



@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("staticgraph.png")
#Now save the new image file
plot.savefig("staticgraph.png")

return render_template("outputs.html")


Outputs.html:



<html>
<head>

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

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

</body>

</html>


I use the flask view function to display an image through the outputs.html file. The catch here is that the static image file that is served keeps changing every time based on user inputs. In other words, I keep overwriting the image file based on the inputs the user has selected.



But the problem is that the changing image file is not served. The old image file that was used for first time render is only displayed for every new input of the user.



I have already referred to old posts regarding serving dynamic content in flask. But none of them served useful.










share|improve this question
























  • The backslashes `` in your paths should probably be escaped..?
    – thebjorn
    Nov 8 at 6:48












  • @thebjorn I have changed the format of that line. Though it doesn't work.
    – Aishu
    Nov 8 at 6:51













up vote
5
down vote

favorite









up vote
5
down vote

favorite











I have a flask view function as below:



@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("staticgraph.png")
#Now save the new image file
plot.savefig("staticgraph.png")

return render_template("outputs.html")


Outputs.html:



<html>
<head>

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

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

</body>

</html>


I use the flask view function to display an image through the outputs.html file. The catch here is that the static image file that is served keeps changing every time based on user inputs. In other words, I keep overwriting the image file based on the inputs the user has selected.



But the problem is that the changing image file is not served. The old image file that was used for first time render is only displayed for every new input of the user.



I have already referred to old posts regarding serving dynamic content in flask. But none of them served useful.










share|improve this question















I have a flask view function as below:



@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("staticgraph.png")
#Now save the new image file
plot.savefig("staticgraph.png")

return render_template("outputs.html")


Outputs.html:



<html>
<head>

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

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

</body>

</html>


I use the flask view function to display an image through the outputs.html file. The catch here is that the static image file that is served keeps changing every time based on user inputs. In other words, I keep overwriting the image file based on the inputs the user has selected.



But the problem is that the changing image file is not served. The old image file that was used for first time render is only displayed for every new input of the user.



I have already referred to old posts regarding serving dynamic content in flask. But none of them served useful.







python html flask






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 7:11









petezurich

3,41381633




3,41381633










asked Nov 8 at 6:41









Aishu

536




536












  • The backslashes `` in your paths should probably be escaped..?
    – thebjorn
    Nov 8 at 6:48












  • @thebjorn I have changed the format of that line. Though it doesn't work.
    – Aishu
    Nov 8 at 6:51


















  • The backslashes `` in your paths should probably be escaped..?
    – thebjorn
    Nov 8 at 6:48












  • @thebjorn I have changed the format of that line. Though it doesn't work.
    – Aishu
    Nov 8 at 6:51
















The backslashes `` in your paths should probably be escaped..?
– thebjorn
Nov 8 at 6:48






The backslashes `` in your paths should probably be escaped..?
– thebjorn
Nov 8 at 6:48














@thebjorn I have changed the format of that line. Though it doesn't work.
– Aishu
Nov 8 at 6:51




@thebjorn I have changed the format of that line. Though it doesn't work.
– Aishu
Nov 8 at 6:51












2 Answers
2






active

oldest

votes

















up vote
3
down vote



accepted










thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3



Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.



@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>





share|improve this answer






























    up vote
    3
    down vote













    You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).



    To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.



    update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):



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


    or use the last-modified attribute (not always reliable):



    from hashlib import md5
    fname = 'static/graph.png'
    modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
    fname += "?v" + checksum


    both of these methods will serve a cached version as long as the file doesn't change.






    share|improve this answer























    • The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
      – Aishu
      Nov 8 at 7:27











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202636%2frender-dynamically-changing-images-with-same-filenames-in-flask%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    3
    down vote



    accepted










    thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3



    Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.



    @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>





    share|improve this answer



























      up vote
      3
      down vote



      accepted










      thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3



      Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.



      @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>





      share|improve this answer

























        up vote
        3
        down vote



        accepted







        up vote
        3
        down vote



        accepted






        thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3



        Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.



        @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>





        share|improve this answer














        thebjorn's solution is valid. I have found multiple posts on Stack Overflow which suggest identical solutions. To view them, search for how to not cache images on Google. link link2 link3



        Below is my solution to your problem. This will delete graph file and create new one with plot.savefig on every GET request to /myfunc. I was not sure on which request you wanted this behavior.



        @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>






        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 8 at 8:42

























        answered Nov 8 at 8:03









        Dinko Pehar

        613324




        613324
























            up vote
            3
            down vote













            You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).



            To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.



            update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):



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


            or use the last-modified attribute (not always reliable):



            from hashlib import md5
            fname = 'static/graph.png'
            modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
            fname += "?v" + checksum


            both of these methods will serve a cached version as long as the file doesn't change.






            share|improve this answer























            • The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
              – Aishu
              Nov 8 at 7:27















            up vote
            3
            down vote













            You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).



            To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.



            update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):



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


            or use the last-modified attribute (not always reliable):



            from hashlib import md5
            fname = 'static/graph.png'
            modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
            fname += "?v" + checksum


            both of these methods will serve a cached version as long as the file doesn't change.






            share|improve this answer























            • The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
              – Aishu
              Nov 8 at 7:27













            up vote
            3
            down vote










            up vote
            3
            down vote









            You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).



            To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.



            update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):



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


            or use the last-modified attribute (not always reliable):



            from hashlib import md5
            fname = 'static/graph.png'
            modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
            fname += "?v" + checksum


            both of these methods will serve a cached version as long as the file doesn't change.






            share|improve this answer














            You're running into a caching issue. Static resources, like images, are cached at every point in the chain between your server and the browser. This is a good thing. Most reasonable systems are set up to cache images for at least 1 year at the server (and that's if they're not cached in the browser).



            To bust through this cache issue, you'll need to either (i) give the files new names, (ii) reconfigure Vary headers to indicate they shouldn't be cached, or (iii) add a uniqueness fragment -- e.g. instead of using static/graph.png, add a timestamp 'static/graph.png?v=' + (new Date()).valueOf() or a md5 hash.



            update: Dinko has given you a fine answer (do read the links he provides). To add cache-busting on the server side, without creating new files, you can calculate an md5 checksum (disadvantage: you'll need to read the entire file):



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


            or use the last-modified attribute (not always reliable):



            from hashlib import md5
            fname = 'static/graph.png'
            modified_tstamp = str(int(os.stat(fname).st_mtime * 10**6))
            fname += "?v" + checksum


            both of these methods will serve a cached version as long as the file doesn't change.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Nov 8 at 9:14

























            answered Nov 8 at 7:19









            thebjorn

            12.6k44885




            12.6k44885












            • The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
              – Aishu
              Nov 8 at 7:27


















            • The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
              – Aishu
              Nov 8 at 7:27
















            The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
            – Aishu
            Nov 8 at 7:27




            The statement for the uniqueness('static/graph.png?v=' + (new Date()).valueOf()) that you mentioned throws a syntax error. Are u sure it is a valid python statement. Can you elaborate a bit more? I do not want to change the file names since I'm not willing to dump the memory.
            – Aishu
            Nov 8 at 7:27


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53202636%2frender-dynamically-changing-images-with-same-filenames-in-flask%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            這個網誌中的熱門文章

            Xamarin.form Move up view when keyboard appear

            Post-Redirect-Get with Spring WebFlux and Thymeleaf

            Anylogic : not able to use stopDelay()