Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cache SQL Alchemy calls with Flask-Cache and Redis?

I have a Flask app that takes parameters from a web form, queries a DB with SQL Alchemy and returns Jinja-generated HTML showing a table with the results. I want to cache the calls to the DB. I looked into Redis (Using redis as an LRU cache for postgres), which led me to http://pythonhosted.org/Flask-Cache/.

Now I am trying to use Redis + Flask-Cache to cache the calls to the DB. Based on the Flask-Cache docs, it seems like I need to set up a custom Redis cache.

class RedisCache(BaseCache):     def __init__(self, servers, default_timeout=500):         pass  def redis(app, config, args, kwargs):    args.append(app.config['REDIS_SERVERS'])    return RedisCache(*args, **kwargs) 

From there I would need to something like:

# not sure what to put for args or kwargs cache = redis(app, config={'CACHE_TYPE': 'redis'})  app = Flask(__name__) cache.init_app(app) 

I have two questions:

  1. What do I put for args and kwargs? What do these mean? How do I set up a Redis cache with Flask-Cache?

  2. Once the cache is set up, it seems like I would want to somehow "memoize" the calls the DB so that if the method gets the same query it has the output cached. How do I do this? My best guess would be to wrap the call the SQL Alchemy in a method that could then be given memoize decorator? That way if two identical queries were passed to the method, Flask-Cache would recognize this and return to the appropriate response. I'm guessing that it would look like this:

    @cache.memoize(timeout=50) def queryDB(q):     return q.all() 

This seems like a fairly common use of Redis + Flask + Flask-Cache + SQL Alchemy, but I am unable to find a complete example to follow. If someone could post one, that would be super helpful -- but for me and for others down the line.

like image 914
bernie2436 Avatar asked Jul 05 '14 18:07

bernie2436


2 Answers

You don't need to create custom RedisCache class. The docs is just teaching how you would create new backends that are not available in flask-cache. But RedisCache is already available in werkzeug >= 0.7, which you might have already installed because it is one of the core dependencies of flask.

This is how I could run the flask-cache with redis backend:

import time from flask import Flask from flask_cache import Cache  app = Flask(__name__) cache = Cache(app, config={'CACHE_TYPE': 'redis'})  @cache.memoize(timeout=60) def query_db():     time.sleep(5)     return "Results from DB"  @app.route('/') def index():     return query_db()  app.run(debug=True) 

The reason you're getting "ImportError: redis is not a valid FlaskCache backend" is probably because you don't have redis (python library) installed which you can simply install by:
pip install redis.

like image 107
suzanshakya Avatar answered Sep 21 '22 16:09

suzanshakya


your redis args would look something like this:

cache = Cache(app, config={     'CACHE_TYPE': 'redis',     'CACHE_KEY_PREFIX': 'fcache',     'CACHE_REDIS_HOST': 'localhost',     'CACHE_REDIS_PORT': '6379',     'CACHE_REDIS_URL': 'redis://localhost:6379'     }) 

Putting the @cache.memoize over a method that grabs the info from the DB should work.

like image 31
Riz Avatar answered Sep 25 '22 16:09

Riz