27

我有一个 Flask 应用程序,它从 Web 表单中获取参数,使用 SQL Alchemy 查询数据库并返回 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. 一旦设置了缓存,似乎我想以某种方式“记忆”调用数据库,这样如果方法获得相同的查询,它就会缓存输出。我该怎么做呢?我最好的猜测是将调用 SQL Alchemy 包装在一个方法中,然后可以给它 memoize 装饰器?这样,如果将两个相同的查询传递给该方法,Flask-Cache 将识别出这一点并返回适当的响应。我猜它看起来像这样:

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

这似乎是 Redis + Flask + Flask-Cache + SQL Alchemy 的一个相当常见的用法,但我无法找到一个完整的示例来遵循。如果有人可以发布一个,那将非常有帮助——但对我和其他人来说。

4

2 回答 2

51

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.

于 2014-07-09T11:41:26.963 回答
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'
    })

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

于 2014-07-08T17:13:47.960 回答