【问题标题】:flask-cache memoize URL query string parameters as wellflask-cache memoize URL 查询字符串参数以及
【发布时间】:2017-11-08 22:06:05
【问题描述】:

flask-cache 扩展有一个@cache.memoize 装饰器来缓存视图,包括视图的*args**kwargs。然而,我的一些观点也采用 URL 查询字符串,例如/foo/image?width=640。装饰器在被装饰的视图函数中增加了一个make_cache_key方法,可以用来自定义缓存键

但是我不知道如何在正常请求上下文之外获取request.args

任何想法如何使@cache.memoize 也适用于 URL 查询字符串?

【问题讨论】:

  • 您可以从视图中提取图像生成函数并缓存它的结果。
  • 是的,成功了。
  • 这是一个非常令人沮丧的答案,因为它是在搜索使用 flask-cache 和如何使用 url 参数管理路由时出现的,但没有提供实际答案。

标签: python flask


【解决方案1】:

你可以使用flask-caching:

Flask-Cache 扩展的延续

你可以用它来做这样的事情:

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

来自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.

【讨论】:

  • 我只是赞成你在 GithHub 中的评论和这个答案;)
【解决方案2】:

我今天遇到了同样的问题,但在互联网上没有找到任何示例,所以我玩了一下。

这是我的 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')

您可以使用 request.url 代替路径和散列参数。我还需要将用户语言添加到密钥中。

缓存视图:

@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

它有效,但我认为它有点麻烦。事实证明,key_prefix 可以是生成整个 cache_key 的可调用对象。因此我们可以这样做:

@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

我只是想出了这个,还没有在生产中使用它——所以它可能不适用于所有情况。

【讨论】:

  • 谢谢!这对我有用:def make_cache_key(*args, **kwargs): return request.url
  • 这可能会导致redis中重复数据的堆积,不是吗?如果您请求说,/comments?blah=blah/comments?foo=foo,它们都会产生相同的结果,因为例如参数被忽略,响应都会被缓存。
  • @reptilecus 这是一个有效的观点!但对于典型用户可能不会出现实际问题(他们不一定会使用 URL)。在任何情况下,都可以采用类似的动态方式,具有更强的一致性:def make_cache_key(*args, **kwargs): return (request.path,) + (arg for arg in args) + (entry for entry in sorted(kwargs.items()))(未经测试,只是一个起点)
  • 为了支持列表参数,您可以将request.args返回的ImmutableMultiDict转换为setsdict{k, set(s) for k, s in request.args.lists()}但@EyalLevin的建议要好得多:@ 987654321@.
  • 我一直在寻找这个!很好的答案。 Flask-Caching 确实有一些缺乏/模糊的文档。
【解决方案3】:

从 0.3.4 版开始,key_prefix 可以是可调用的:

0.3.4 版中的新功能:可以选择是不带参数但返回将用作 cache_key 的字符串的可调用对象。

这是文档:Flask-Cache

【讨论】:

    【解决方案4】:

    感谢 SmoeAsdine El Hrychy,这是我的版本;它为当前 URL + 查询字符串生成一个键(在我看来,这一定是一个常见的需求)。

    注意:

    • 如果您请求?a=foo&b=bar?b=bar&a=foo,查询字符串将被排序以保持不变(最初我做了(k, v) for k, val in flask.request.args.viewitems() for v in sorted(val),但我也更改为对键进行排序)
    • 它支持多次出现的相同键,即:?a=foo&a=bar(并将返回与?a=bar&a=foo相同的键)
    • key_prefix 参数仅适用于 cached 而不适用于 memoize,至少从 Flask-Cache 0.13.1 开始,并且由于它采用 URL 路径,因此它应该适合大多数 memoize 用例

    代码:

    import flask
    import urllib
    
    def cache_key():
        args = flask.request.args
        key = flask.request.path + '?' + urllib.urlencode([
            (k, v) for k in sorted(args) for v in sorted(args.getlist(k))
        ])
        return key
    
    # ...
    import time
    
    @app.route('/test')
    @cache.cached(timeout=600, key_prefix=cache_key)
    def test():
        return time.time()
    
    @app.route('/<value>/test')
    @cache.cached(timeout=3600, key_prefix=cache_key)
    def value_test(value):
        return flask.jsonify(time=time.time(), value=value)
    

    【讨论】:

      【解决方案5】:

      因为我不想让兄弟自己做更多的工作,比如引用 args,但是下面的代码可以工作并且可以满足我的要求:

      from flask import request
      
      def cache_key():
          return request.url
      
      @main.route("/test/", methods=['GET'])
      @cache.cached(timeout=10, key_prefix=cache_key)
      def do_somthing():
          return "hello %s" % str(request.args)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-31
        • 2011-11-16
        • 1970-01-01
        • 2022-01-22
        • 2012-06-02
        相关资源
        最近更新 更多