我在一个Django应用程序下有许多站点,我想在其上实现站点范围的缓存。然而事实证明这是一个真正的麻烦。
发生的事情是settings.CACHE_MIDDLEWARE_KEY_PREFIX
在启动时设置一次,我无法继续并根据当前站点的内容进行更改。因此,如果缓存了网址http://website1.com/abc/
的页面,则http://website2.com/abc/
会呈现http://website1.com/abc/
的缓存版本。这两个网站都在同一个Django实例上运行,因为Django Sites似乎允许我们这样做。
这是一种不正确的方法吗?因为我无法在运行时动态设置CACHE_MIDDLEWARE_KEY_PREFIX
,所以我无法使用Django的站点范围缓存来缓存多个站点。我也无法为模板和视图缓存执行此操作。
我得到的印象是,真正需要设置的方式是每个站点都需要自己的Django实例,除了设置文件之外几乎完全相同,在我的情况下,它只会因{{1}的值而不同}}。这些Django实例都读写同一个数据库。这让我很担心,因为它可能会产生许多新问题。
我是走在正确的轨道上还是我错误地认为多站点架构需要如何工作?我已经检查了Django文档,并没有真正提到如何处理为多个站点提供服务的Django应用程序的缓存(不是低级缓存)。
答案 0 :(得分:1)
(免责声明:以下内容仅供参考,尚未经过测试。请少量食用。)
可以使用vary_on_headers视图装饰器在缓存键中包含'Host'标头。这应该导致包含HTTP主机头的缓存键,从而有效地隔离您的站点的缓存。
@vary_on_headers('Host')
def my_view(request):
# ....
当然,这只能在每个视图的基础上工作,并且必须在所有视图中添加装饰器可能会非常麻烦。
深入研究source of @vary_on_headers揭示了patch_vary_headers()的使用,可以在中间件中使用{{3}}在网站级别应用相同的行为。有点像:
from django.utils.cache import patch_vary_headers
class VaryByHostMiddleware(object):
def process_response(self, request, response):
patch_vary_headers(response, ('Host',))
return response
答案 1 :(得分:1)
我最近遇到了这个问题。我基于documentation所做的是创建一个自定义方法,将网站ID添加到用于缓存视图的密钥。
在settings.py中添加KEY_FUNCTION参数:
CACHES = {
'default': {
'BACKEND': 'path.to.backend',
'LOCATION': 'path.to.location',
'TIMEOUT': 60,
'KEY_FUNCTION': 'path.to.custom.make_key_per_site',
'OPTIONS': {
'MAX_ENTRIES': 1000
}
}
}
我的自定义make_key方法:
def make_key_per_site(key, key_prefix, version):
site_id = ''
try:
site = get_current_site() # Whatever you use to get your site's data
site_id = site['id']
except:
pass
return ':'.join([key_prefix, site_id, str(version), key])
答案 2 :(得分:0)
您需要在django.util.cache中将get_full_path更改为build_absolute_uri
def _generate_cache_header_key(key_prefix, request):
"""Returns a cache key for the header cache."""
#path = md5_constructor(iri_to_uri(request.get_full_path()))
path = md5_constructor(iri_to_uri(request.build_absolute_uri())) # patch using full path
cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
key_prefix, path.hexdigest())
return _i18n_cache_key_suffix(request, cache_key)
def _generate_cache_key(request, method, headerlist, key_prefix):
"""Returns a cache key from the headers given in the header list."""
ctx = md5_constructor()
for header in headerlist:
value = request.META.get(header, None)
if value is not None:
ctx.update(value)
#path = md5_constructor(iri_to_uri(request.get_full_path()))
path = md5_constructor(iri_to_uri(request.build_absolute_uri()))
cache_key = 'views.decorators.cache.cache_page.%s.%s.%s.%s' % (
key_prefix, request.method, path.hexdigest(), ctx.hexdigest())
return _i18n_cache_key_suffix(request, cache_key)
或者为多站点创建自己稍微更改过的缓存中间件。 http://macrotoma.blogspot.com/2012/06/custom-multisite-caching-on-django.html