Flask-Cache doesn't distinguish between GET and POST

1.3k Views Asked by At

I have a Flask route structured like so:

@app.route('/rootpath1/<path:path>')
@app.route('/rootpath2/<path:path>', methods=['GET', 'POST'])
@cache.cached()
def rootpath():
    ...

POSTs to '/rootpath2/' for a given page are typically retrieved from cache (when a cached value is present), which is usually the last GET request.

For example, a user would visit '/rootpath2/myform', fill out and then submit the form. The form would post to '/rootpath2/myform' and the user would be returned to the same URI with a message indicating that the form submission was successful (or that errors occurred, if they did).

The problem here is that a GET always precedes the POST, and the POST always triggers a cache hit and returns that value.

Is there a way for Flask-Cache to distinguish between GETs and POSTs and handle them according (only caching GETs)?

1

There are 1 best solutions below

0
On

Yes. The cache decorator provides an unless kwarg that accepts a callable. Return True from the callable to cancel caching. Test it out with the following:

from flask import Flask, request, render_template_string
from flask.ext.cache import Cache

app = Flask('foo')
cache = Cache(app,config={'CACHE_TYPE': 'simple'})

t = '<form action="/" method="POST">{{request.form.dob}}<input name="dob" type="date" value={{request.form.dob}} /><button>Go</button></form>'

def only_cache_get(*args, **kwargs):
    if request.method == 'GET':
        return False

    return True


@app.route('/', methods=['GET', 'POST'])
@cache.cached(timeout=100, unless=only_cache_get)
def home():
    if request.method == 'GET':
        print('GET is not cached')
        return render_template_string(t)

    if request.method == 'POST':
        print('POST is not cached')
        return render_template_string(t)

app.run(debug=True)