Флажок-кеш memoize параметры строки запроса URL-адреса также

Расширение флагового кэша имеет декодер @cache.memoize для кэширования представления, включая представление *args и **kwargs. Однако некоторые из моих представлений также содержат строку запроса URL, например /foo/image?width=640. Декоратор добавляет метод make_cache_key к декорированной функции просмотра, которая может использоваться для настройки ключа кеша

Однако я не знаю, как получить request.args вне контекста обычного запроса.

Любые идеи о том, как заставить @cache.memoize работать с строками запроса URL-адреса?

Ответы

Ответ 1

У меня была такая же проблема сегодня, и я не нашел никакого примера в Интернете, поэтому немного поиграл.

Это моя 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

Я только что придумал это и еще не использовал его в производстве, поэтому он может не работать во всех случаях.

Ответ 2

Начиная с версии 0.3.4, key_prefix может быть вызываемым:

Новое в версии 0.3.4: Может быть необязательно вызываемым, которое не принимает аргументов, но возвращает строку, которая будет использоваться как cache_key.

Вот документ: Flask-Cache

Ответ 3

благодаря Smoe и Asdine 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)

Ответ 4

Вы можете использовать flask-caching:

Продолжение расширения флагов-кешей

С помощью чего вы можете сделать что-то вроде этого:

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

Документы из исходный код:

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

Ответ 5

так как я не хочу, чтобы брат сам делал больше работы, как цитирует аргументы, но следующий код может работать и может удовлетворить мое требование:

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)