Commit f6c99166 authored by Jannis Leidel's avatar Jannis Leidel
Browse files

Fixed #4992 -- Respect the GET request query string when creating cache keys....

Fixed #4992 -- Respect the GET request query string when creating cache keys. Thanks PeterKz and guettli for the initial patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@15705 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent a9ace146
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -166,7 +166,9 @@ class HttpRequest(object):
        return host

    def get_full_path(self):
        return ''
        # RFC 3986 requires query string arguments to be in the ASCII range.
        # Rather than crash if this doesn't happen, we encode defensively.
        return '%s%s' % (self.path, self.META.get('QUERY_STRING', '') and ('?' + iri_to_uri(self.META.get('QUERY_STRING', ''))) or '')

    def build_absolute_uri(self, location=None):
        """
+2 −2
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ Django's ``LocaleMiddleware``.

More details about how the caching works:

* Only parameter-less GET or HEAD-requests with status code 200 are cached.
* Only GET or HEAD-requests with status code 200 are cached.

* The number of seconds each page is stored for is set by the "max-age" section
  of the response's "Cache-Control" header, falling back to the
@@ -135,7 +135,7 @@ class FetchFromCacheMiddleware(object):
        Checks whether the page is already cached and returns the cached
        version if available.
        """
        if not request.method in ('GET', 'HEAD') or request.GET:
        if not request.method in ('GET', 'HEAD'):
            request._cache_update_cache = False
            return None # Don't bother checking the cache.

+7 −7
Original line number Diff line number Diff line
@@ -160,24 +160,24 @@ def _generate_cache_key(request, method, headerlist, key_prefix):
        value = request.META.get(header, None)
        if value is not None:
            ctx.update(value)
    path = md5_constructor(iri_to_uri(request.path))
    path = md5_constructor(iri_to_uri(request.get_full_path()))
    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)

def _generate_cache_header_key(key_prefix, request):
    """Returns a cache key for the header cache."""
    path = md5_constructor(iri_to_uri(request.path))
    path = md5_constructor(iri_to_uri(request.get_full_path()))
    cache_key = 'views.decorators.cache.cache_header.%s.%s' % (
        key_prefix, path.hexdigest())
    return _i18n_cache_key_suffix(request, cache_key)

def get_cache_key(request, key_prefix=None, method='GET', cache=None):
    """
    Returns a cache key based on the request path. It can be used in the
    request phase because it pulls the list of headers to take into account
    from the global path registry and uses those to build a cache key to check
    against.
    Returns a cache key based on the request path and query. It can be used
    in the request phase because it pulls the list of headers to take into
    account from the global path registry and uses those to build a cache key
    to check against.

    If there is no headerlist stored, the page needs to be rebuilt, so this
    function returns None.
@@ -220,7 +220,7 @@ def learn_cache_key(request, response, cache_timeout=None, key_prefix=None, cach
        return _generate_cache_key(request, request.method, headerlist, key_prefix)
    else:
        # if there is no Vary header, we still need a cache key
        # for the request.path
        # for the request.get_full_path()
        cache.set(cache_key, [], cache_timeout)
        return _generate_cache_key(request, request.method, [], key_prefix)

+3 −0
Original line number Diff line number Diff line
@@ -169,6 +169,9 @@ Secondly, :ref:`Versioning <cache_versioning>`, :ref:`site-wide
prefixing <cache_key_prefixing>` and :ref:`transformation
<cache_key_transformation>` has been added to the cache API.

Thirdly, the :ref:`cache key creation <using-vary-headers>` has been
updated to take the GET request query string into account.

Lastly, support for pylibmc_ has been added to the memcached cache
backend.

+6 −2
Original line number Diff line number Diff line
@@ -962,9 +962,13 @@ mechanism should take into account when building its cache key. For example, if
the contents of a Web page depend on a user's language preference, the page is
said to "vary on language."

.. versionchanged:: 1.3
    In Django 1.3 the full request path -- including the query -- is used
    to create the cache keys, instead of only the path component in Django 1.2.

By default, Django's cache system creates its cache keys using the requested
path (e.g., ``"/stories/2005/jun/23/bank_robbed/"``). This means every request
to that URL will use the same cached version, regardless of user-agent
path and query -- e.g., ``"/stories/2005/?order_by=author"``. This means every
request to that URL will use the same cached version, regardless of user-agent
differences such as cookies or language preferences. However, if this page
produces different content based on some difference in request headers -- such
as a cookie, or a language, or a user-agent -- you'll need to use the ``Vary``
Loading