Django - 多站点站点缓存

发布于 2024-10-15 05:30:16 字数 734 浏览 2 评论 0原文

我在一个 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 实例,除了设置文件之外,它几乎是相同的,在我的例子中,设置文件的区别仅在于 CACHE_MIDDLEWARE_KEY_PREFIX 的值代码>.这些 Django 实例都读取和写入同一个数据库。这让我担心,因为它可能会产生许多新问题。

我是否走在正确的道路上,或者我是否错误地理解了多站点架构需要如何工作?我检查了 Django 文档,并没有真正提到如何处理服务多个站点的 Django 应用程序的缓存(这不是低级缓存)。

I have a number of sites under one Django application that I would like to implement site wide caching on. However it is proving to be a real hassle.

what happens is that settings.CACHE_MIDDLEWARE_KEY_PREFIX is set once on startup, and I cannot go ahead and change it depending on what the current site is. As a result if a page of url http://website1.com/abc/ is cached then http://website2.com/abc/ renders the cached version of http://website1.com/abc/. Both these websites are running on the same Django instance as this is what Django Sites appears to allow us to do.

Is this an incorrect approach? Because I cannot dynamically set CACHE_MIDDLEWARE_KEY_PREFIX during runtime I am unable to cache multiple sites using Django's Site wide caching. I also am unable to do this for template and view caching.

I get the impression that the way this really needs to be setup is that each site needs its own Django instance which is pretty much identical except for the settings file, which in my case will differ only by the value of CACHE_MIDDLEWARE_KEY_PREFIX. These Django instances all read and write to the same database. This concerns me as it could create a number of new issues.

Am I going down the right track or am I mistaken about how multi site architecture needs to work? I have checked the Django docs and there is not real mention of how to handle caching (that isn't low level caching) for Django applications that serve multiple sites.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

清风疏影 2024-10-22 05:30:16

(免责声明:以下内容纯粹是猜测,尚未经过测试。请谨慎食用。)

可能可以使用 vary_on_headers 视图装饰器在缓存键中包含 'Host' 标头。这应该会导致缓存键包含 HTTP 主机标头,从而有效地隔离站点的缓存。

@vary_on_headers('Host')
def my_view(request):
    # ....

当然,这只适用于每个视图,并且必须向所有视图添加装饰器可能会很麻烦。

深入研究@vary_on_headers的来源揭示了 patch_vary_headers() 的使用,其中一个可能能够在中间件中使用以在站点级别应用相同的行为。大致如下:

from django.utils.cache import patch_vary_headers

class VaryByHostMiddleware(object):
    def process_response(self, request, response):
        patch_vary_headers(response, ('Host',))
        return response

(Disclaimer: the following is purely speculation and has not been tested. Consume with a pinch of salt.)

It might be possible to use the vary_on_headers view decorator to include the 'Host' header in the cache key. That should result in cache keys that include the HTTP Host header, thus effectively isolating the caches for your sites.

@vary_on_headers('Host')
def my_view(request):
    # ....

Of course, that will only work on a per-view basis, and having to add a decorator to all views can be a big hassle.

Digging into the source of @vary_on_headers reveals the use of patch_vary_headers() which one might be able to use in a middleware to apply the same behaviour on a site level. Something along the lines of:

from django.utils.cache import patch_vary_headers

class VaryByHostMiddleware(object):
    def process_response(self, request, response):
        patch_vary_headers(response, ('Host',))
        return response
单身情人 2024-10-22 05:30:16

我最近遇到了这个问题。我根据 文档 所做的是创建将站点 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])

I faced this problem recently. What I did based on the documentation was to create a custom method to add the site id to the key used to cache the view.

In settings.py add the KEY_FUNCTION argument:

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
        }
    }
}

And my custom make_key method:

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])
七度光 2024-10-22 05:30:16

您需要将 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

You need to change get_full_path to build_absolute_uri in django.util.cache

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)

Or create you own slightly changed cache middleware for multisite.
http://macrotoma.blogspot.com/2012/06/custom-multisite-caching-on-django.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文