Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flask-cache memoize URL query string parameters as well

Tags:

python

flask

The flask-cache extension has a @cache.memoize decorator to cache a view including the view's *args and **kwargs. Some of my views however take a URL query string as well, for example /foo/image?width=640. The decorator adds a make_cache_key method to the decorated view function that can be used to customise the cache key

However I do not know how to get the request.args outside of the normal request context.

Any ideas how to make the @cache.memoize work with URL query strings as well?

like image 904
Adrian Avatar asked Feb 23 '12 12:02

Adrian


2 Answers

You can use flask-caching:

Continuation of the Flask-Cache Extension

With which you can do something like this:

@app.route("/") @cache.cached(timeout=10, query_string=True) def index():     return render_template('index.html') 

Docs from source code:

:param query_string: Default False. When True, the cache key                      used will be the result of hashing the                      ordered query string parameters. This                      avoids creating different caches for                      the same query just because the parameters                      were passed in a different order. See                      _make_cache_key_query_string() for more                      details. 
like image 125
Eyal Levin Avatar answered Sep 23 '22 00:09

Eyal Levin


I had the same problem today and didn't find any example on the internet so I played around a little.

This is my make_cache_key:

def make_cache_key(*args, **kwargs):     path = request.path     args = str(hash(frozenset(request.args.items())))     lang = get_locale()     return (path + args + lang).encode('utf-8') 

You could use request.url instead of path and the hashed args. I needed to add the users language to the key as well.

Caching a view:

@app.route("/test") @cache.cached(timeout=50) def test():     a = request.args.get('a')     b = request.args.get('b')     return a + b test.make_cache_key = make_cache_key 

It works but i think it's kind of cumbersome. It turned out, that the key_prefix can be a callable which generates the whole cache_key. Therefore we can do this:

@app.route("/test2") @cache.cached(timeout=50, key_prefix=make_cache_key) def test2():     a = request.args.get('a')     b = request.args.get('b')     return a + b 

I just came up with this and haven't used it in production yet – so it may not work in all cases.

like image 31
Smoe Avatar answered Sep 24 '22 00:09

Smoe