Django - кеширование сайтов на нескольких сайтах

У меня есть несколько сайтов под одним приложением Django, на которых я хотел бы реализовать кэширование всего сайта. Однако это оказывается настоящим хлопотом.

что происходит, что settings.CACHE_MIDDLEWARE_KEY_PREFIX устанавливается один раз при запуске, и я не могу пойти дальше и изменить его в зависимости от текущего сайта. В результате, если страница URL 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, которые обслуживают несколько сайтов.

3 ответа

(Отказ от ответственности: нижеследующее является чисто предположением и не было проверено. Потребляйте с щепоткой соли.)

Можно использовать декоратор представления var_on_headers для включения заголовка "Host" в ключ кеша. Это должно привести к ключам кэша, которые включают заголовок HTTP Host, таким образом эффективно изолируя кэши для ваших сайтов.

@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

Я столкнулся с этой проблемой недавно. Основываясь на документации, я создал собственный метод для добавления идентификатора сайта в ключ, используемый для кэширования представления.

В 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])

Вам нужно изменить get_full_path на build_absolute_uri в 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)

Или создайте свой собственный слегка измененный промежуточный кеш для мультисайта. http://macrotoma.blogspot.com/2012/06/custom-multisite-caching-on-django.html

Другие вопросы по тегам