如何使用Flask-Cache和Redis缓存SQL Alchemy调用?

28

我有一个Flask应用程序,从Web表单中获取参数,使用SQLAlchemy查询数据库,并返回由Jinja生成的HTML,显示结果表格。我想缓存对数据库的调用。我研究了Redis (将Redis用作Postgres的LRU缓存),这使我找到了http://pythonhosted.org/Flask-Cache/

现在我正在尝试使用Redis + Flask-Cache来缓存对数据库的调用。根据Flask-Cache文档,似乎我需要设置一个自定义的Redis缓存。

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)

从那里开始,我需要做类似于以下的事情:

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

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

我有两个问题:

  1. 我应该在 argskwargs 中填什么?这些是什么意思?如何使用 Flask-Cache 设置 Redis 缓存?

  2. 一旦缓存设置好了,看起来我会想要以某种方式“memoize”调用数据库,以便如果方法获得相同的查询,它就会具有输出缓存。我该如何做到这一点?我的最佳猜测是将 SQL Alchemy 调用封装在一个方法中,然后给该方法提供 memoize 装饰器?这样,如果两个相同的查询被传递给该方法,Flask-Cache 会识别这一点并返回适当的响应。我猜它会看起来像这样:

@cache.memoize(timeout=50)
def queryDB(q):
    return q.all()
这似乎是 Redis + Flask + Flask-Cache + SQL Alchemy 的常见用法,但我无法找到一个完整的示例来遵循。如果有人能够发布一个,那将非常有帮助 - 对于我和其他人来说都是如此。


我遇到了一个问题,将查询对象作为参数传递会导致使用对象的内存地址进行记忆化。通过包装类解决了这个问题。希望这能帮助到某些人。 - ezdazuzena
2个回答

51
你不需要创建自定义的 RedisCache 类。文档只是在教你如何创建不在 flask-cache 中可用的新后端。但是 RedisCache 已经在 werkzeug >= 0.7 中可用,你可能已经安装了它,因为它是 flask 的核心依赖之一。
这是我如何使用 redis 后端运行 flask-cache:
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)

如果你遇到了 "ImportError: redis is not a valid FlaskCache backend" 的错误,那很可能是因为你没有安装 redis (Python 库),你可以通过以下命令简单安装:
pip install redis


在我的情况下,需要执行pip install redis命令来安装Redis。请记得按照Riz在他的回答中所描述的配置Redis连接。 - Ctrl-C
4
注意:使用 from flask flaskt.ext.cache import Cache 导入 Flask 扩展已被弃用,请改用 from flask_cache import Cache。请注意,在导入时不要更改原有的意思。 - Ronnie Beltran

18

你的Redis参数看起来会像这样:

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'
    })

将 @cache.memoize 放在从数据库中获取信息的方法上应该起作用。


如果我跟随这个例子,我会遇到“ImportError: redis is not a valid FlaskCache backend”错误。 - bernie2436
如果我将CACHE_TYPE更改为“redis”,则会出现错误:flask_cache:可能由于缓存后端而导致异常.... AttributeError:'Flask'对象没有'mget'属性。 - bernie2436
3
请确保已安装了redis Python库。可以通过运行pip install redis命令进行安装。 - Riz
你如何为生产环境设置 Redis 主机(不使用 localhost 作为主机)?我正在尝试寻找一个好的在线指南来设置 Redis 主机,但找不到任何东西。 - nosh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接