在我开发烧瓶应用程序的隆隆声中,我找到了缓存装饰器。装饰师是一段简短的、写得很好的代码,但我觉得它忽略了以下几点:
我试图改进它的方法是有一个装饰器,它允许我在每个视图中定义一个缓存控制策略,这个策略同时涉及客户端和服务器端,方法是遵循下面的流程图,该流程图摘自Google Guru Ilya Grigorik的HTTP缓存文章。

装饰师的代码是:
import binascii
import datetime
from flask import Response, make_response
def cached(cacheable = False, must_revalidate = True, client_only = True, client_timeout = 0, server_timeout = 5 * 60, key='view/%s'):
"""
@see https://jakearchibald.com/2016/caching-best-practices/
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/http-caching
"""
def decorator(f):
@wraps(f)
def decorated_function(*args, **kwargs):
cache_key = key % request.full_path # include querystring
cache_policy = ''
etag = ''
if not cacheable:
cache_policy += ', no-store' # tells the browser not to cache at all
else:
if must_revalidate: # this looks contradicting if you haven't read the article.
# no-cache doesn't mean "don't cache", it means it must check
# (or "revalidate" as it calls it) with the server before
# using the cached resource
cache_policy += ', no-cache'
else:
# Also must-revalidate doesn't mean "must revalidate", it
# means the local resource can be used if it's younger than
# the provided max-age, otherwise it must revalidate
cache_policy += ', must-revalidate'
if client_only:
cache_policy += ', private'
else:
cache_policy += ', public'
cache_policy += ', max-age=%d' % (client_timeout)
headers = {}
cache_policy = cache_policy.strip(',')
headers['Cache-Control'] = cache_policy
now = datetime.datetime.utcnow()
client_etag = request.headers.get('If-None-Match')
response = cache.get(cache_key)
# respect the hard-refresh
if response is not None and request.headers.get('Cache-Control', '') != 'no-cache':
headers['X-Cache'] = 'HIT from Server'
cached_etag = response.headers.get('ETag')
if client_etag and cached_etag and client_etag == cached_etag:
headers['X-Cache'] = 'HIT from Client'
headers['X-Last-Modified'] = response.headers.get('X-LastModified')
response = make_response('', 304)
else:
response = make_response(f(*args, **kwargs))
if response.status_code == 200 and request.method in ['GET', 'HEAD']:
headers['X-Cache'] = 'MISS'
# - Added the headers to the response object instead of the
# headers dict so they get cached too
# - If you can find any faster random algorithm go for it.
response.headers.add('ETag', binascii.hexlify(os.urandom(4)))
response.headers.add('X-Last-Modified', str(now))
cache.set(cache_key, response, timeout=server_timeout)
response.headers.extend(headers)
return response
return decorated_function
return decorator然后,装潢师可以使用类似的
@pages.route('/')
@cached(True, must_revalidate=True, client_only=False, client_timeout=120, server_timeout=5*60)
def index():
"""Serve client-side application shell."""
return render_template('shell.html', model = get_default_model())请注意,装饰器上的cache是由Werkzeug提供的,在这种情况下它是内存中的,但是它可以是redis、memcached等等,因为Werkzeug缓存为它们提供了一个通用的高级API,同时使底层的实现细节远离开发人员的视线或担忧。
我想听听你对此的反馈,与“标准”装潢师相比,这是否是一个有价值的改进,在那里它可以被改进和简化。
发布于 2023-01-07 02:53:21
关于这方面的反馈意见,这是否是一项有价值的改进
是。这太棒了。
我和你一样担心它是否可以简化。但是遗憾的是,web缓存规则有点复杂。
https://codereview.stackexchange.com/questions/147038
复制相似问题