|
1 ======================== |
|
2 Django's cache framework |
|
3 ======================== |
|
4 |
|
5 A fundamental tradeoff in dynamic Web sites is, well, they're dynamic. Each |
|
6 time a user requests a page, the Web server makes all sorts of calculations -- |
|
7 from database queries to template rendering to business logic -- to create the |
|
8 page that your site's visitor sees. This is a lot more expensive, from a |
|
9 processing-overhead perspective, than your standard read-a-file-off-the-filesystem |
|
10 server arrangement. |
|
11 |
|
12 For most Web applications, this overhead isn't a big deal. Most Web |
|
13 applications aren't washingtonpost.com or slashdot.org; they're simply small- |
|
14 to medium-sized sites with so-so traffic. But for medium- to high-traffic |
|
15 sites, it's essential to cut as much overhead as possible. |
|
16 |
|
17 That's where caching comes in. |
|
18 |
|
19 To cache something is to save the result of an expensive calculation so that |
|
20 you don't have to perform the calculation next time. Here's some pseudocode |
|
21 explaining how this would work for a dynamically generated Web page:: |
|
22 |
|
23 given a URL, try finding that page in the cache |
|
24 if the page is in the cache: |
|
25 return the cached page |
|
26 else: |
|
27 generate the page |
|
28 save the generated page in the cache (for next time) |
|
29 return the generated page |
|
30 |
|
31 Django comes with a robust cache system that lets you save dynamic pages so |
|
32 they don't have to be calculated for each request. For convenience, Django |
|
33 offers different levels of cache granularity: You can cache the output of |
|
34 specific views, you can cache only the pieces that are difficult to produce, or |
|
35 you can cache your entire site. |
|
36 |
|
37 Django also works well with "upstream" caches, such as Squid |
|
38 (http://www.squid-cache.org/) and browser-based caches. These are the types of |
|
39 caches that you don't directly control but to which you can provide hints (via |
|
40 HTTP headers) about which parts of your site should be cached, and how. |
|
41 |
|
42 Setting up the cache |
|
43 ==================== |
|
44 |
|
45 The cache system requires a small amount of setup. Namely, you have to tell it |
|
46 where your cached data should live -- whether in a database, on the filesystem |
|
47 or directly in memory. This is an important decision that affects your cache's |
|
48 performance; yes, some cache types are faster than others. |
|
49 |
|
50 Your cache preference goes in the ``CACHE_BACKEND`` setting in your settings |
|
51 file. Here's an explanation of all available values for CACHE_BACKEND. |
|
52 |
|
53 Memcached |
|
54 --------- |
|
55 |
|
56 By far the fastest, most efficient type of cache available to Django, Memcached |
|
57 is an entirely memory-based cache framework originally developed to handle high |
|
58 loads at LiveJournal.com and subsequently open-sourced by Danga Interactive. |
|
59 It's used by sites such as Slashdot and Wikipedia to reduce database access and |
|
60 dramatically increase site performance. |
|
61 |
|
62 Memcached is available for free at http://danga.com/memcached/ . It runs as a |
|
63 daemon and is allotted a specified amount of RAM. All it does is provide an |
|
64 interface -- a *super-lightning-fast* interface -- for adding, retrieving and |
|
65 deleting arbitrary data in the cache. All data is stored directly in memory, |
|
66 so there's no overhead of database or filesystem usage. |
|
67 |
|
68 After installing Memcached itself, you'll need to install the Memcached Python |
|
69 bindings. They're in a single Python module, memcache.py, available at |
|
70 ftp://ftp.tummy.com/pub/python-memcached/ . If that URL is no longer valid, |
|
71 just go to the Memcached Web site (http://www.danga.com/memcached/) and get the |
|
72 Python bindings from the "Client APIs" section. |
|
73 |
|
74 To use Memcached with Django, set ``CACHE_BACKEND`` to |
|
75 ``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached |
|
76 daemon and ``port`` is the port on which Memcached is running. |
|
77 |
|
78 In this example, Memcached is running on localhost (127.0.0.1) port 11211:: |
|
79 |
|
80 CACHE_BACKEND = 'memcached://127.0.0.1:11211/' |
|
81 |
|
82 One excellent feature of Memcached is its ability to share cache over multiple |
|
83 servers. To take advantage of this feature, include all server addresses in |
|
84 ``CACHE_BACKEND``, separated by semicolons. In this example, the cache is |
|
85 shared over Memcached instances running on IP address 172.19.26.240 and |
|
86 172.19.26.242, both on port 11211:: |
|
87 |
|
88 CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/' |
|
89 |
|
90 Memory-based caching has one disadvantage: Because the cached data is stored in |
|
91 memory, the data will be lost if your server crashes. Clearly, memory isn't |
|
92 intended for permanent data storage, so don't rely on memory-based caching as |
|
93 your only data storage. Actually, none of the Django caching backends should be |
|
94 used for permanent storage -- they're all intended to be solutions for caching, |
|
95 not storage -- but we point this out here because memory-based caching is |
|
96 particularly temporary. |
|
97 |
|
98 Database caching |
|
99 ---------------- |
|
100 |
|
101 To use a database table as your cache backend, first create a cache table in |
|
102 your database by running this command:: |
|
103 |
|
104 python manage.py createcachetable [cache_table_name] |
|
105 |
|
106 ...where ``[cache_table_name]`` is the name of the database table to create. |
|
107 (This name can be whatever you want, as long as it's a valid table name that's |
|
108 not already being used in your database.) This command creates a single table |
|
109 in your database that is in the proper format that Django's database-cache |
|
110 system expects. |
|
111 |
|
112 Once you've created that database table, set your ``CACHE_BACKEND`` setting to |
|
113 ``"db://tablename/"``, where ``tablename`` is the name of the database table. |
|
114 In this example, the cache table's name is ``my_cache_table``: |
|
115 |
|
116 CACHE_BACKEND = 'db://my_cache_table' |
|
117 |
|
118 Database caching works best if you've got a fast, well-indexed database server. |
|
119 |
|
120 Filesystem caching |
|
121 ------------------ |
|
122 |
|
123 To store cached items on a filesystem, use the ``"file://"`` cache type for |
|
124 ``CACHE_BACKEND``. For example, to store cached data in ``/var/tmp/django_cache``, |
|
125 use this setting:: |
|
126 |
|
127 CACHE_BACKEND = 'file:///var/tmp/django_cache' |
|
128 |
|
129 Note that there are three forward slashes toward the beginning of that example. |
|
130 The first two are for ``file://``, and the third is the first character of the |
|
131 directory path, ``/var/tmp/django_cache``. |
|
132 |
|
133 The directory path should be absolute -- that is, it should start at the root |
|
134 of your filesystem. It doesn't matter whether you put a slash at the end of the |
|
135 setting. |
|
136 |
|
137 Make sure the directory pointed-to by this setting exists and is readable and |
|
138 writable by the system user under which your Web server runs. Continuing the |
|
139 above example, if your server runs as the user ``apache``, make sure the |
|
140 directory ``/var/tmp/django_cache`` exists and is readable and writable by the |
|
141 user ``apache``. |
|
142 |
|
143 Local-memory caching |
|
144 -------------------- |
|
145 |
|
146 If you want the speed advantages of in-memory caching but don't have the |
|
147 capability of running Memcached, consider the local-memory cache backend. This |
|
148 cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to |
|
149 ``"locmem:///"``. For example:: |
|
150 |
|
151 CACHE_BACKEND = 'locmem:///' |
|
152 |
|
153 Simple caching (for development) |
|
154 -------------------------------- |
|
155 |
|
156 A simple, single-process memory cache is available as ``"simple:///"``. This |
|
157 merely saves cached data in-process, which means it should only be used in |
|
158 development or testing environments. For example:: |
|
159 |
|
160 CACHE_BACKEND = 'simple:///' |
|
161 |
|
162 Dummy caching (for development) |
|
163 ------------------------------- |
|
164 |
|
165 Finally, Django comes with a "dummy" cache that doesn't actually cache -- it |
|
166 just implements the cache interface without doing anything. |
|
167 |
|
168 This is useful if you have a production site that uses heavy-duty caching in |
|
169 various places but a development/test environment on which you don't want to |
|
170 cache. In that case, set ``CACHE_BACKEND`` to ``"dummy:///"`` in the settings |
|
171 file for your development environment. As a result, your development |
|
172 environment won't use caching and your production environment still will. |
|
173 |
|
174 CACHE_BACKEND arguments |
|
175 ----------------------- |
|
176 |
|
177 All caches may take arguments. They're given in query-string style on the |
|
178 ``CACHE_BACKEND`` setting. Valid arguments are: |
|
179 |
|
180 timeout |
|
181 Default timeout, in seconds, to use for the cache. Defaults to 5 |
|
182 minutes (300 seconds). |
|
183 |
|
184 max_entries |
|
185 For the simple and database backends, the maximum number of entries |
|
186 allowed in the cache before it is cleaned. Defaults to 300. |
|
187 |
|
188 cull_percentage |
|
189 The percentage of entries that are culled when max_entries is reached. |
|
190 The actual percentage is 1/cull_percentage, so set cull_percentage=3 to |
|
191 cull 1/3 of the entries when max_entries is reached. |
|
192 |
|
193 A value of 0 for cull_percentage means that the entire cache will be |
|
194 dumped when max_entries is reached. This makes culling *much* faster |
|
195 at the expense of more cache misses. |
|
196 |
|
197 In this example, ``timeout`` is set to ``60``:: |
|
198 |
|
199 CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=60" |
|
200 |
|
201 In this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``:: |
|
202 |
|
203 CACHE_BACKEND = "memcached://127.0.0.1:11211/?timeout=30&max_entries=400" |
|
204 |
|
205 Invalid arguments are silently ignored, as are invalid values of known |
|
206 arguments. |
|
207 |
|
208 The per-site cache |
|
209 ================== |
|
210 |
|
211 Once the cache is set up, the simplest way to use caching is to cache your |
|
212 entire site. Just add ``'django.middleware.cache.CacheMiddleware'`` to your |
|
213 ``MIDDLEWARE_CLASSES`` setting, as in this example:: |
|
214 |
|
215 MIDDLEWARE_CLASSES = ( |
|
216 'django.middleware.cache.CacheMiddleware', |
|
217 'django.middleware.common.CommonMiddleware', |
|
218 ) |
|
219 |
|
220 (The order of ``MIDDLEWARE_CLASSES`` matters. See "Order of MIDDLEWARE_CLASSES" |
|
221 below.) |
|
222 |
|
223 Then, add the following required settings to your Django settings file: |
|
224 |
|
225 * ``CACHE_MIDDLEWARE_SECONDS`` -- The number of seconds each page should be |
|
226 cached. |
|
227 * ``CACHE_MIDDLEWARE_KEY_PREFIX`` -- If the cache is shared across multiple |
|
228 sites using the same Django installation, set this to the name of the site, |
|
229 or some other string that is unique to this Django instance, to prevent key |
|
230 collisions. Use an empty string if you don't care. |
|
231 |
|
232 The cache middleware caches every page that doesn't have GET or POST |
|
233 parameters. Optionally, if the ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting is |
|
234 ``True``, only anonymous requests (i.e., not those made by a logged-in user) |
|
235 will be cached. This is a simple and effective way of disabling caching for any |
|
236 user-specific pages (include Django's admin interface). Note that if you use |
|
237 ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY``, you should make sure you've activated |
|
238 ``AuthenticationMiddleware`` and that ``AuthenticationMiddleware`` appears |
|
239 before ``CacheMiddleware`` in your ``MIDDLEWARE_CLASSES``. |
|
240 |
|
241 Additionally, ``CacheMiddleware`` automatically sets a few headers in each |
|
242 ``HttpResponse``: |
|
243 |
|
244 * Sets the ``Last-Modified`` header to the current date/time when a fresh |
|
245 (uncached) version of the page is requested. |
|
246 * Sets the ``Expires`` header to the current date/time plus the defined |
|
247 ``CACHE_MIDDLEWARE_SECONDS``. |
|
248 * Sets the ``Cache-Control`` header to give a max age for the page -- again, |
|
249 from the ``CACHE_MIDDLEWARE_SECONDS`` setting. |
|
250 |
|
251 See the `middleware documentation`_ for more on middleware. |
|
252 |
|
253 .. _`middleware documentation`: ../middleware/ |
|
254 |
|
255 The per-view cache |
|
256 ================== |
|
257 |
|
258 A more granular way to use the caching framework is by caching the output of |
|
259 individual views. ``django.views.decorators.cache`` defines a ``cache_page`` |
|
260 decorator that will automatically cache the view's response for you. It's easy |
|
261 to use:: |
|
262 |
|
263 from django.views.decorators.cache import cache_page |
|
264 |
|
265 def slashdot_this(request): |
|
266 ... |
|
267 |
|
268 slashdot_this = cache_page(slashdot_this, 60 * 15) |
|
269 |
|
270 Or, using Python 2.4's decorator syntax:: |
|
271 |
|
272 @cache_page(60 * 15) |
|
273 def slashdot_this(request): |
|
274 ... |
|
275 |
|
276 ``cache_page`` takes a single argument: the cache timeout, in seconds. In the |
|
277 above example, the result of the ``slashdot_this()`` view will be cached for 15 |
|
278 minutes. |
|
279 |
|
280 The low-level cache API |
|
281 ======================= |
|
282 |
|
283 Sometimes, however, caching an entire rendered page doesn't gain you very much. |
|
284 For example, you may find it's only necessary to cache the result of an |
|
285 intensive database query. In cases like this, you can use the low-level cache |
|
286 API to store objects in the cache with any level of granularity you like. |
|
287 |
|
288 The cache API is simple. The cache module, ``django.core.cache``, exports a |
|
289 ``cache`` object that's automatically created from the ``CACHE_BACKEND`` |
|
290 setting:: |
|
291 |
|
292 >>> from django.core.cache import cache |
|
293 |
|
294 The basic interface is ``set(key, value, timeout_seconds)`` and ``get(key)``:: |
|
295 |
|
296 >>> cache.set('my_key', 'hello, world!', 30) |
|
297 >>> cache.get('my_key') |
|
298 'hello, world!' |
|
299 |
|
300 The ``timeout_seconds`` argument is optional and defaults to the ``timeout`` |
|
301 argument in the ``CACHE_BACKEND`` setting (explained above). |
|
302 |
|
303 If the object doesn't exist in the cache, ``cache.get()`` returns ``None``:: |
|
304 |
|
305 >>> cache.get('some_other_key') |
|
306 None |
|
307 |
|
308 # Wait 30 seconds for 'my_key' to expire... |
|
309 |
|
310 >>> cache.get('my_key') |
|
311 None |
|
312 |
|
313 get() can take a ``default`` argument:: |
|
314 |
|
315 >>> cache.get('my_key', 'has expired') |
|
316 'has expired' |
|
317 |
|
318 There's also a get_many() interface that only hits the cache once. get_many() |
|
319 returns a dictionary with all the keys you asked for that actually exist in the |
|
320 cache (and haven't expired):: |
|
321 |
|
322 >>> cache.set('a', 1) |
|
323 >>> cache.set('b', 2) |
|
324 >>> cache.set('c', 3) |
|
325 >>> cache.get_many(['a', 'b', 'c']) |
|
326 {'a': 1, 'b': 2, 'c': 3} |
|
327 |
|
328 Finally, you can delete keys explicitly with ``delete()``. This is an easy way |
|
329 of clearing the cache for a particular object:: |
|
330 |
|
331 >>> cache.delete('a') |
|
332 |
|
333 That's it. The cache has very few restrictions: You can cache any object that |
|
334 can be pickled safely, although keys must be strings. |
|
335 |
|
336 Upstream caches |
|
337 =============== |
|
338 |
|
339 So far, this document has focused on caching your *own* data. But another type |
|
340 of caching is relevant to Web development, too: caching performed by "upstream" |
|
341 caches. These are systems that cache pages for users even before the request |
|
342 reaches your Web site. |
|
343 |
|
344 Here are a few examples of upstream caches: |
|
345 |
|
346 * Your ISP may cache certain pages, so if you requested a page from |
|
347 somedomain.com, your ISP would send you the page without having to access |
|
348 somedomain.com directly. |
|
349 |
|
350 * Your Django Web site may sit behind a Squid Web proxy |
|
351 (http://www.squid-cache.org/) that caches pages for performance. In this |
|
352 case, each request first would be handled by Squid, and it'd only be |
|
353 passed to your application if needed. |
|
354 |
|
355 * Your Web browser caches pages, too. If a Web page sends out the right |
|
356 headers, your browser will use the local (cached) copy for subsequent |
|
357 requests to that page. |
|
358 |
|
359 Upstream caching is a nice efficiency boost, but there's a danger to it: |
|
360 Many Web pages' contents differ based on authentication and a host of other |
|
361 variables, and cache systems that blindly save pages based purely on URLs could |
|
362 expose incorrect or sensitive data to subsequent visitors to those pages. |
|
363 |
|
364 For example, say you operate a Web e-mail system, and the contents of the |
|
365 "inbox" page obviously depend on which user is logged in. If an ISP blindly |
|
366 cached your site, then the first user who logged in through that ISP would have |
|
367 his user-specific inbox page cached for subsequent visitors to the site. That's |
|
368 not cool. |
|
369 |
|
370 Fortunately, HTTP provides a solution to this problem: A set of HTTP headers |
|
371 exist to instruct caching mechanisms to differ their cache contents depending |
|
372 on designated variables, and to tell caching mechanisms not to cache particular |
|
373 pages. |
|
374 |
|
375 Using Vary headers |
|
376 ================== |
|
377 |
|
378 One of these headers is ``Vary``. It defines which request headers a cache |
|
379 mechanism should take into account when building its cache key. For example, if |
|
380 the contents of a Web page depend on a user's language preference, the page is |
|
381 said to "vary on language." |
|
382 |
|
383 By default, Django's cache system creates its cache keys using the requested |
|
384 path -- e.g., ``"/stories/2005/jun/23/bank_robbed/"``. This means every request |
|
385 to that URL will use the same cached version, regardless of user-agent |
|
386 differences such as cookies or language preferences. |
|
387 |
|
388 That's where ``Vary`` comes in. |
|
389 |
|
390 If your Django-powered page outputs different content based on some difference |
|
391 in request headers -- such as a cookie, or language, or user-agent -- you'll |
|
392 need to use the ``Vary`` header to tell caching mechanisms that the page output |
|
393 depends on those things. |
|
394 |
|
395 To do this in Django, use the convenient ``vary_on_headers`` view decorator, |
|
396 like so:: |
|
397 |
|
398 from django.views.decorators.vary import vary_on_headers |
|
399 |
|
400 # Python 2.3 syntax. |
|
401 def my_view(request): |
|
402 ... |
|
403 my_view = vary_on_headers(my_view, 'User-Agent') |
|
404 |
|
405 # Python 2.4 decorator syntax. |
|
406 @vary_on_headers('User-Agent') |
|
407 def my_view(request): |
|
408 ... |
|
409 |
|
410 In this case, a caching mechanism (such as Django's own cache middleware) will |
|
411 cache a separate version of the page for each unique user-agent. |
|
412 |
|
413 The advantage to using the ``vary_on_headers`` decorator rather than manually |
|
414 setting the ``Vary`` header (using something like |
|
415 ``response['Vary'] = 'user-agent'``) is that the decorator adds to the ``Vary`` |
|
416 header (which may already exist) rather than setting it from scratch. |
|
417 |
|
418 You can pass multiple headers to ``vary_on_headers()``:: |
|
419 |
|
420 @vary_on_headers('User-Agent', 'Cookie') |
|
421 def my_view(request): |
|
422 ... |
|
423 |
|
424 Because varying on cookie is such a common case, there's a ``vary_on_cookie`` |
|
425 decorator. These two views are equivalent:: |
|
426 |
|
427 @vary_on_cookie |
|
428 def my_view(request): |
|
429 ... |
|
430 |
|
431 @vary_on_headers('Cookie') |
|
432 def my_view(request): |
|
433 ... |
|
434 |
|
435 Also note that the headers you pass to ``vary_on_headers`` are not case |
|
436 sensitive. ``"User-Agent"`` is the same thing as ``"user-agent"``. |
|
437 |
|
438 You can also use a helper function, ``django.utils.cache.patch_vary_headers``, |
|
439 directly:: |
|
440 |
|
441 from django.utils.cache import patch_vary_headers |
|
442 def my_view(request): |
|
443 ... |
|
444 response = render_to_response('template_name', context) |
|
445 patch_vary_headers(response, ['Cookie']) |
|
446 return response |
|
447 |
|
448 ``patch_vary_headers`` takes an ``HttpResponse`` instance as its first argument |
|
449 and a list/tuple of header names as its second argument. |
|
450 |
|
451 For more on Vary headers, see the `official Vary spec`_. |
|
452 |
|
453 .. _`official Vary spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44 |
|
454 |
|
455 Controlling cache: Using other headers |
|
456 ====================================== |
|
457 |
|
458 Another problem with caching is the privacy of data and the question of where |
|
459 data should be stored in a cascade of caches. |
|
460 |
|
461 A user usually faces two kinds of caches: his own browser cache (a private |
|
462 cache) and his provider's cache (a public cache). A public cache is used by |
|
463 multiple users and controlled by someone else. This poses problems with |
|
464 sensitive data: You don't want, say, your banking-account number stored in a |
|
465 public cache. So Web applications need a way to tell caches which data is |
|
466 private and which is public. |
|
467 |
|
468 The solution is to indicate a page's cache should be "private." To do this in |
|
469 Django, use the ``cache_control`` view decorator. Example:: |
|
470 |
|
471 from django.views.decorators.cache import cache_control |
|
472 @cache_control(private=True) |
|
473 def my_view(request): |
|
474 ... |
|
475 |
|
476 This decorator takes care of sending out the appropriate HTTP header behind the |
|
477 scenes. |
|
478 |
|
479 There are a few other ways to control cache parameters. For example, HTTP |
|
480 allows applications to do the following: |
|
481 |
|
482 * Define the maximum time a page should be cached. |
|
483 * Specify whether a cache should always check for newer versions, only |
|
484 delivering the cached content when there are no changes. (Some caches |
|
485 might deliver cached content even if the server page changed -- simply |
|
486 because the cache copy isn't yet expired.) |
|
487 |
|
488 In Django, use the ``cache_control`` view decorator to specify these cache |
|
489 parameters. In this example, ``cache_control`` tells caches to revalidate the |
|
490 cache on every access and to store cached versions for, at most, 3600 seconds:: |
|
491 |
|
492 from django.views.decorators.cache import cache_control |
|
493 @cache_control(must_revalidate=True, max_age=3600) |
|
494 def my_view(request): |
|
495 ... |
|
496 |
|
497 Any valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``. |
|
498 Here's a full list: |
|
499 |
|
500 * ``public=True`` |
|
501 * ``private=True`` |
|
502 * ``no_cache=True`` |
|
503 * ``no_transform=True`` |
|
504 * ``must_revalidate=True`` |
|
505 * ``proxy_revalidate=True`` |
|
506 * ``max_age=num_seconds`` |
|
507 * ``s_maxage=num_seconds`` |
|
508 |
|
509 For explanation of Cache-Control HTTP directives, see the `Cache-Control spec`_. |
|
510 |
|
511 (Note that the caching middleware already sets the cache header's max-age with |
|
512 the value of the ``CACHE_MIDDLEWARE_SETTINGS`` setting. If you use a custom |
|
513 ``max_age`` in a ``cache_control`` decorator, the decorator will take |
|
514 precedence, and the header values will be merged correctly.) |
|
515 |
|
516 .. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9 |
|
517 |
|
518 Other optimizations |
|
519 =================== |
|
520 |
|
521 Django comes with a few other pieces of middleware that can help optimize your |
|
522 apps' performance: |
|
523 |
|
524 * ``django.middleware.http.ConditionalGetMiddleware`` adds support for |
|
525 conditional GET. This makes use of ``ETag`` and ``Last-Modified`` |
|
526 headers. |
|
527 |
|
528 * ``django.middleware.gzip.GZipMiddleware`` compresses content for browsers |
|
529 that understand gzip compression (all modern browsers). |
|
530 |
|
531 Order of MIDDLEWARE_CLASSES |
|
532 =========================== |
|
533 |
|
534 If you use ``CacheMiddleware``, it's important to put it in the right place |
|
535 within the ``MIDDLEWARE_CLASSES`` setting, because the cache middleware needs |
|
536 to know which headers by which to vary the cache storage. Middleware always |
|
537 adds something the ``Vary`` response header when it can. |
|
538 |
|
539 Put the ``CacheMiddleware`` after any middlewares that might add something to |
|
540 the ``Vary`` header. The following middlewares do so: |
|
541 |
|
542 * ``SessionMiddleware`` adds ``Cookie`` |
|
543 * ``GZipMiddleware`` adds ``Accept-Encoding`` |