Earlier today I needed to cache a view with the @cache_page decorator. The output of this view changes depending on whether the user making the request is logged in or not. Pretty standard stuff.
However, I quickly discovered that @cache_page was caching both authenticated and anonymous requests under the same cache key. This led to the cache serving either the authenticated or anonymous version of the page, whichever was cached first. Not good.
In short, @cache_page created the same cache key for both authenticated and anonymous versions because a Vary header hadn’t been set yet on the response. If the
Vary: Cookie HTTP header had been set, the cache key would have changed depending on the value of the Cookie header and everything would have worked just fine.
The cleanest fix I could find is to use two decorators. First is to wrap the real view function with @vary_on_cookie (to set the
Vary: Cookie header) and then wrap that function with @cache_page (to actually cache the page). Like so:
<code>@cache_page(60*60) @vary_on_cookie def expensive_func(request): # ... </code>
After doing this, everything worked.