10

I have a template showing various entries that the author can edit/delete. Users can delete their posts clicking on Delete

After the deletion the user gets redirected to the entries page, but the item is still there, and the page needs to be reloaded again to show the deletion effect. If i disable caching the problem disappears, but i really want to have caches in all the other pages...

adding these tags didn't work, i think my browser just ignores them

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />

I'm enabling the cache trough:

@app.after_request
def add_header(response):    
response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
response.headers['Cache-Control'] = 'public, max-age=600'
return response

Is there a way I can disable it for a specific page?

edit

as suggested i tried using a wrapper:

def no_cache(f):
    def new_func(*args, **kwargs):
        resp = make_response(f(*args, **kwargs))
        resp.cache_control.no_cache = True
        return resp
    return update_wrapper(new_func, f)

and wrap the page i want wihtout cache in a @no_cache decorator, still had no luck...

Luca Brozzi
  • 335
  • 1
  • 3
  • 15

3 Answers3

8

You can try adding cache control headers only if there are no such headers for a specific page:

@app.after_request
def add_header(response):    
  response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
  if ('Cache-Control' not in response.headers):
    response.headers['Cache-Control'] = 'public, max-age=600'
  return response

And in your page code - e.g.:

@app.route('/page_without_cache')
def page_without_cache():
   response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
   response.headers['Pragma'] = 'no-cache'
   return 'hello'

The point is that you shouldn't override your headers in @app.after_request for all pages - only for those where cache isn't turned off explicitly.

Further, you might want to move the code adding headers to a wrapper such as @no_cache - so you can use it just like that:

 @app.route('/page_without_cache')
 @no_cache
 def page_without_cache():
   return 'hello'
NikitaBaksalyar
  • 2,414
  • 1
  • 24
  • 27
  • 1
    thanks for pointing out that i can't add cache control headers if they're already there, i didn't think of that... i tried doing as you suggested, trying with a wrapper and trying to just add the response headers, but the cache is still there for some reason... – Luca Brozzi Feb 20 '15 at 11:57
  • @LucaBrozzi, please check that you're getting the headers you want in the Chrome/Mozilla dev tools. Refer to e.g. this SO answer if you don't know how to do it: http://stackoverflow.com/questions/4423061/view-http-headers-in-google-chrome. If you clearly see that there is no `Cache-Control: no-cache` header, it's still a problem with overriden headers in your `@app.after_request` handler. – NikitaBaksalyar Feb 20 '15 at 11:59
  • nah i had forgotten to change a line, your solution was right, thank you very much – Luca Brozzi Feb 20 '15 at 15:37
5

While the answer of NikitaBaksalyar is pointing into the right direction. I had trouble getting it to work. The page code gave me an error with missing response.

The solution is quite simple. Use the make_response method.

from flask import make_response

For per page cache-control settings:

    @app.route('/profile/details', methods=['GET', 'POST'])
    def profile_details():
        ...<page specific logic>...
        response = make_response(render_template('profile-details.html'))
        response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
        response.headers['Pragma'] = 'no-cache'
        return response

Default cache-control settings:

    @app.after_request
    def add_header(response):
        response.headers['X-UA-Compatible'] = 'IE=Edge,chrome=1'
        if ('Cache-Control' not in response.headers):
            response.headers['Cache-Control'] = 'public, max-age=600'
        return response
tvb
  • 783
  • 1
  • 10
  • 21
1

Use make_response

Than set the response.headers for disabling cache. Like bellow.

from flask import make_response

@app.route('/')
def your_page_route():
    ...
    response = make_response(render_template('index.html', ... )) # your template variables
    response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
    response.headers["Pragma"] = "no-cache"
    response.headers["Expires"] = "0"
    response.headers['Cache-Control'] = 'public, max-age=0'
    return response
imbr
  • 6,226
  • 4
  • 53
  • 65