bernie2436 bernie2436 - 6 months ago 39
SQL Question

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 w/ SQL alchemy and returns a jinja-generated template 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 lead 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 setup 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

cache = redis(app, config={'CACHE_TYPE': 'redis'}) //not sure what to put for args or kwards?

app = Flask(__name__)
cache.init_app(app)


I have two questions:

First: what do I put for args and kwargs? What do these mean? How do I setup a redis cache with flask cache?

Second: once the cache is set up it seems like I would want to somehow "memoize" the calls the 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.

Answer

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.ext.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.