Django custom cache_page decorater возвращает ошибку при первом запуске, после чего все в порядке - PullRequest
0 голосов
/ 26 февраля 2019

Я создал собственный cache_page декоратор для своего приложения.Он не работает при первом запуске и выдает ошибку, связанную с промежуточным программным обеспечением:

content_encoding = response.get("Content-Encoding", "")

AttributeError: 'bool' object has no attribute 'get'

Но при втором и дальнейшем запуске он работает, потому чтокеш был установлен.Я установил django debug_toolbar и добавил промежуточное ПО cors в свое промежуточное ПО.Кто-нибудь может помочь в этом?Вот мой пользовательский func декоратор:

def cache_page(timeout):
    """custom cache page decorator"""
    def decorator(func):
        @wraps(func)
        def wrapper(request, *args, **kwargs):
            print("wrapp", request)
            cache_key = hashlib.md5(
                iri_to_uri(request.build_absolute_uri()).encode('ascii')
            ).hexdigest()
            cached_data = cache.get(cache_key)
            if cached_data is not None:
                return cached_data
            response = func(request, *args, **kwargs)
            if (isinstance(response, Response) and response.status_code in (200, 301, 302, 304)):
                cache_timeout = timeout() if callable(timeout) else timeout
                if hasattr(response, 'render') and callable(response.render):
                    response.add_post_render_callback(
                        lambda r: cache.set(cache_key, r, cache_timeout)
                    )
                else:
                    cache.set(cache_key, response, cache_timeout)
            return response
        return wrapper
    return decorator

1 Ответ

0 голосов
/ 08 марта 2019

Протестировано с Django 2.2b:

Я использовал этот миксин:

class CacheKeyDispatchMixin:
    def dispatch(self, *args, **kwargs):
        if self.request.method == 'GET' or self.request.method == 'HEAD':
            url_to_cache = '/{0}{1}'.format(get_language(), self.request.get_full_path())
            cache_hash = calculate_xxxhash(url_to_cache)
            data = cache.get(cache_hash)
            if not data:
                response = super(CacheKeyDispatchMixin, self).dispatch(*args, **kwargs)
                if response.status_code == 200:
                    response.render()
                    cache.set(cache_hash, response)
                    logger.info('Cache added {0} ({1})'.format(url_to_cache, cache_hash))
                return response
            logger.info('Cache hit {0} ({1}).'.format(url_to_cache, cache_hash))
            return data

        return super(CacheKeyDispatchMixin, self).dispatch(*args, **kwargs)

В основном вы можете вызвать render() перед его кэшированием.

...