Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Made a bunch of edits to docs/topics/cache.txt, mostly based on stuff…

… from the Django Book

git-svn-id: http://code.djangoproject.com/svn/django/trunk@10055 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 957c721594deb9a6e91a83a7e1ff37502ec1bb97 1 parent f87575f
Adrian Holovaty authored March 14, 2009

Showing 1 changed file with 202 additions and 117 deletions. Show diff stats Hide diff stats

  1. 319  docs/topics/cache.txt
319  docs/topics/cache.txt
@@ -50,7 +50,7 @@ or directly in memory. This is an important decision that affects your cache's
50 50
 performance; yes, some cache types are faster than others.
51 51
 
52 52
 Your cache preference goes in the ``CACHE_BACKEND`` setting in your settings
53  
-file. Here's an explanation of all available values for CACHE_BACKEND.
  53
+file. Here's an explanation of all available values for ``CACHE_BACKEND``.
54 54
 
55 55
 Memcached
56 56
 ---------
@@ -58,18 +58,18 @@ Memcached
58 58
 By far the fastest, most efficient type of cache available to Django, Memcached
59 59
 is an entirely memory-based cache framework originally developed to handle high
60 60
 loads at LiveJournal.com and subsequently open-sourced by Danga Interactive.
61  
-It's used by sites such as Slashdot and Wikipedia to reduce database access and
  61
+It's used by sites such as Facebook and Wikipedia to reduce database access and
62 62
 dramatically increase site performance.
63 63
 
64 64
 Memcached is available for free at http://danga.com/memcached/ . It runs as a
65 65
 daemon and is allotted a specified amount of RAM. All it does is provide an
66  
-interface -- a *lightning-fast* interface -- for adding, retrieving and
67  
-deleting arbitrary data in the cache. All data is stored directly in memory,
68  
-so there's no overhead of database or filesystem usage.
  66
+fast interface for adding, retrieving and deleting arbitrary data in the cache.
  67
+All data is stored directly in memory, so there's no overhead of database or
  68
+filesystem usage.
69 69
 
70 70
 After installing Memcached itself, you'll need to install the Memcached Python
71  
-bindings. Two versions of this are available. Choose and install *one* of the
72  
-following modules:
  71
+bindings, which are not bundled with Django directly. Two versions of this are
  72
+available. Choose and install *one* of the following modules:
73 73
 
74 74
     * The fastest available option is a module called ``cmemcache``, available
75 75
       at http://gijsbert.org/cmemcache/ .
@@ -93,19 +93,29 @@ In this example, Memcached is running on localhost (127.0.0.1) port 11211::
93 93
     CACHE_BACKEND = 'memcached://127.0.0.1:11211/'
94 94
 
95 95
 One excellent feature of Memcached is its ability to share cache over multiple
96  
-servers. To take advantage of this feature, include all server addresses in
97  
-``CACHE_BACKEND``, separated by semicolons. In this example, the cache is
98  
-shared over Memcached instances running on IP address 172.19.26.240 and
99  
-172.19.26.242, both on port 11211::
  96
+servers. This means you can run Memcached daemons on multiple machines, and the
  97
+program will treat the group of machines as a *single* cache, without the need
  98
+to duplicate cache values on each machine. To take advantage of this feature,
  99
+include all server addresses in ``CACHE_BACKEND``, separated by semicolons.
  100
+
  101
+In this example, the cache is shared over Memcached instances running on IP
  102
+address 172.19.26.240 and 172.19.26.242, both on port 11211::
100 103
 
101 104
     CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11211/'
102 105
 
103  
-Memory-based caching has one disadvantage: Because the cached data is stored in
104  
-memory, the data will be lost if your server crashes. Clearly, memory isn't
105  
-intended for permanent data storage, so don't rely on memory-based caching as
106  
-your only data storage. Actually, none of the Django caching backends should be
107  
-used for permanent storage -- they're all intended to be solutions for caching,
108  
-not storage -- but we point this out here because memory-based caching is
  106
+In the following example, the cache is shared over Memcached instances running
  107
+on the IP addresses 172.19.26.240 (port 11211), 172.19.26.242 (port 11212), and
  108
+172.19.26.244 (port 11213)::
  109
+
  110
+    CACHE_BACKEND = 'memcached://172.19.26.240:11211;172.19.26.242:11212;172.19.26.244:11213/'
  111
+
  112
+A final point about Memcached is that memory-based caching has one
  113
+disadvantage: Because the cached data is stored in memory, the data will be
  114
+lost if your server crashes. Clearly, memory isn't intended for permanent data
  115
+storage, so don't rely on memory-based caching as your only data storage.
  116
+Without a doubt, *none* of the Django caching backends should be used for
  117
+permanent storage -- they're all intended to be solutions for caching, not
  118
+storage -- but we point this out here because memory-based caching is
109 119
 particularly temporary.
110 120
 
111 121
 Database caching
@@ -128,6 +138,9 @@ In this example, the cache table's name is ``my_cache_table``::
128 138
 
129 139
     CACHE_BACKEND = 'db://my_cache_table'
130 140
 
  141
+The database caching backend uses the same database as specified in your
  142
+settings file. You can't use a different database backend for your cache table.
  143
+
131 144
 Database caching works best if you've got a fast, well-indexed database server.
132 145
 
133 146
 Filesystem caching
@@ -141,7 +154,10 @@ use this setting::
141 154
 
142 155
 Note that there are three forward slashes toward the beginning of that example.
143 156
 The first two are for ``file://``, and the third is the first character of the
144  
-directory path, ``/var/tmp/django_cache``.
  157
+directory path, ``/var/tmp/django_cache``. If you're on Windows, put the
  158
+drive letter after the ``file://``, like this::
  159
+
  160
+    file://c:/foo/bar
145 161
 
146 162
 The directory path should be absolute -- that is, it should start at the root
147 163
 of your filesystem. It doesn't matter whether you put a slash at the end of the
@@ -153,6 +169,10 @@ above example, if your server runs as the user ``apache``, make sure the
153 169
 directory ``/var/tmp/django_cache`` exists and is readable and writable by the
154 170
 user ``apache``.
155 171
 
  172
+Each cache value will be stored as a separate file whose contents are the
  173
+cache data saved in a serialized ("pickled") format, using Python's ``pickle``
  174
+module. Each file's name is the cache key, escaped for safe filesystem use.
  175
+
156 176
 Local-memory caching
157 177
 --------------------
158 178
 
@@ -166,7 +186,7 @@ cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to
166 186
 Note that each process will have its own private cache instance, which means no
167 187
 cross-process caching is possible. This obviously also means the local memory
168 188
 cache isn't particularly memory-efficient, so it's probably not a good choice
169  
-for production environments.
  189
+for production environments. It's nice for development.
170 190
 
171 191
 Dummy caching (for development)
172 192
 -------------------------------
@@ -175,10 +195,9 @@ Finally, Django comes with a "dummy" cache that doesn't actually cache -- it
175 195
 just implements the cache interface without doing anything.
176 196
 
177 197
 This is useful if you have a production site that uses heavy-duty caching in
178  
-various places but a development/test environment on which you don't want to
179  
-cache. As a result, your development environment won't use caching and your
180  
-production environment still will. To activate dummy caching, set
181  
-``CACHE_BACKEND`` like so::
  198
+various places but a development/test environment where you don't want to cache
  199
+and don't want to have to change your code to special-case the latter. To
  200
+activate dummy caching, set ``CACHE_BACKEND`` like so::
182 201
 
183 202
     CACHE_BACKEND = 'dummy:///'
184 203
 
@@ -205,26 +224,24 @@ been well-tested and are easy to use.
205 224
 CACHE_BACKEND arguments
206 225
 -----------------------
207 226
 
208  
-All caches may take arguments. They're given in query-string style on the
209  
-``CACHE_BACKEND`` setting. Valid arguments are:
  227
+Each cache backend may take arguments. They're given in query-string style on
  228
+the ``CACHE_BACKEND`` setting. Valid arguments are as follows:
210 229
 
211  
-    timeout
212  
-        Default timeout, in seconds, to use for the cache. Defaults to 5
213  
-        minutes (300 seconds).
  230
+    * ``timeout``: The default timeout, in seconds, to use for the cache.
  231
+      This argument defaults to 300 seconds (5 minutes).
214 232
 
215  
-    max_entries
216  
-        For the ``locmem``, ``filesystem`` and ``database`` backends, the
217  
-        maximum number of entries allowed in the cache before it is cleaned.
218  
-        Defaults to 300.
  233
+    * ``max_entries``: For the ``locmem``, ``filesystem`` and ``database``
  234
+      backends, the maximum number of entries allowed in the cache before old
  235
+      values are deleted. This argument defaults to 300.
219 236
 
220  
-    cull_percentage
221  
-        The percentage of entries that are culled when max_entries is reached.
222  
-        The actual percentage is 1/cull_percentage, so set cull_percentage=3 to
223  
-        cull 1/3 of the entries when max_entries is reached.
  237
+    * ``cull_percentage``: The percentage of entries that are culled when
  238
+      ``max_entries`` is reached. The actual ratio is ``1/cull_percentage``, so
  239
+      set ``cull_percentage=2`` to cull half of the entries when ``max_entries``
  240
+      is reached.
224 241
 
225  
-        A value of 0 for cull_percentage means that the entire cache will be
226  
-        dumped when max_entries is reached. This makes culling *much* faster
227  
-        at the expense of more cache misses.
  242
+      A value of ``0`` for ``cull_percentage`` means that the entire cache will
  243
+      be dumped when ``max_entries`` is reached. This makes culling *much*
  244
+      faster at the expense of more cache misses.
228 245
 
229 246
 In this example, ``timeout`` is set to ``60``::
230 247
 
@@ -282,12 +299,14 @@ user-specific pages (include Django's admin interface). Note that if you use
282 299
 Additionally, the cache middleware automatically sets a few headers in each
283 300
 ``HttpResponse``:
284 301
 
285  
-* Sets the ``Last-Modified`` header to the current date/time when a fresh
286  
-  (uncached) version of the page is requested.
287  
-* Sets the ``Expires`` header to the current date/time plus the defined
288  
-  ``CACHE_MIDDLEWARE_SECONDS``.
289  
-* Sets the ``Cache-Control`` header to give a max age for the page -- again,
290  
-  from the ``CACHE_MIDDLEWARE_SECONDS`` setting.
  302
+    * Sets the ``Last-Modified`` header to the current date/time when a fresh
  303
+      (uncached) version of the page is requested.
  304
+
  305
+    * Sets the ``Expires`` header to the current date/time plus the defined
  306
+      ``CACHE_MIDDLEWARE_SECONDS``.
  307
+
  308
+    * Sets the ``Cache-Control`` header to give a max age for the page --
  309
+      again, from the ``CACHE_MIDDLEWARE_SECONDS`` setting.
291 310
 
292 311
 See :ref:`topics-http-middleware` for more on middleware.
293 312
 
@@ -313,20 +332,64 @@ to use::
313 332
 
314 333
     from django.views.decorators.cache import cache_page
315 334
 
316  
-    def slashdot_this(request):
  335
+    def my_view(request):
317 336
         ...
318 337
 
319  
-    slashdot_this = cache_page(slashdot_this, 60 * 15)
  338
+    my_view = cache_page(my_view, 60 * 15)
320 339
 
321 340
 Or, using Python 2.4's decorator syntax::
322 341
 
323 342
     @cache_page(60 * 15)
324  
-    def slashdot_this(request):
  343
+    def my_view(request):
325 344
         ...
326 345
 
327 346
 ``cache_page`` takes a single argument: the cache timeout, in seconds. In the
328  
-above example, the result of the ``slashdot_this()`` view will be cached for 15
329  
-minutes.
  347
+above example, the result of the ``my_view()`` view will be cached for 15
  348
+minutes. (Note that we've written it as ``60 * 15`` for the purpose of
  349
+readability. ``60 * 15`` will be evaluated to ``900`` -- that is, 15 minutes
  350
+multiplied by 60 seconds per minute.)
  351
+
  352
+The per-view cache, like the per-site cache, is keyed off of the URL. If
  353
+multiple URLs point at the same view, each URL will be cached separately.
  354
+Continuing the ``my_view`` example, if your URLconf looks like this::
  355
+
  356
+    urlpatterns = ('',
  357
+        (r'^foo/(\d{1,2})/$', my_view),
  358
+    )
  359
+
  360
+then requests to ``/foo/1/`` and ``/foo/23/`` will be cached separately, as
  361
+you may expect. But once a particular URL (e.g., ``/foo/23/``) has been
  362
+requested, subsequent requests to that URL will use the cache.
  363
+
  364
+Specifying per-view cache in the URLconf
  365
+----------------------------------------
  366
+
  367
+The examples in the previous section have hard-coded the fact that the view is
  368
+cached, because ``cache_page`` alters the ``my_view`` function in place. This
  369
+approach couples your view to the cache system, which is not ideal for several
  370
+reasons. For instance, you might want to reuse the view functions on another,
  371
+cache-less site, or you might want to distribute the views to people who might
  372
+want to use them without being cached. The solution to these problems is to
  373
+specify the per-view cache in the URLconf rather than next to the view functions
  374
+themselves.
  375
+
  376
+Doing so is easy: simply wrap the view function with ``cache_page`` when you
  377
+refer to it in the URLconf. Here's the old URLconf from earlier::
  378
+
  379
+    urlpatterns = ('',
  380
+        (r'^foo/(\d{1,2})/$', my_view),
  381
+    )
  382
+
  383
+Here's the same thing, with ``my_view`` wrapped in ``cache_page``::
  384
+
  385
+    from django.views.decorators.cache import cache_page
  386
+
  387
+    urlpatterns = ('',
  388
+        (r'^foo/(\d{1,2})/$', cache_page(my_view, 60 * 15)),
  389
+    )
  390
+
  391
+If you take this approach, don't forget to import ``cache_page`` within your
  392
+URLconf.
330 393
 
331 394
 Template fragment caching
332 395
 =========================
@@ -374,14 +437,25 @@ timeout in a variable, in one place, and just reuse that value.
374 437
 The low-level cache API
375 438
 =======================
376 439
 
377  
-Sometimes, however, caching an entire rendered page doesn't gain you very much.
378  
-For example, you may find it's only necessary to cache the result of an
379  
-intensive database query. In cases like this, you can use the low-level cache
380  
-API to store objects in the cache with any level of granularity you like.
  440
+Sometimes, caching an entire rendered page doesn't gain you very much and is,
  441
+in fact, inconvenient overkill.
  442
+
  443
+Perhaps, for instance, your site includes a view whose results depend on 
  444
+several expensive queries, the results of which change at different intervals.
  445
+In this case, it would not be ideal to use the full-page caching that the 
  446
+per-site or per-view cache strategies offer, because you wouldn't want to 
  447
+cache the entire result (since some of the data changes often), but you'd still 
  448
+want to cache the results that rarely change.
  449
+
  450
+For cases like this, Django exposes a simple, low-level cache API. You can use
  451
+this API to store objects in the cache with any level of granularity you like.
  452
+You can cache any Python object that can be pickled safely: strings,
  453
+dictionaries, lists of model objects, and so forth. (Most common Python objects
  454
+can be pickled; refer to the Python documentation for more information about
  455
+pickling.)
381 456
 
382  
-The cache API is simple. The cache module, ``django.core.cache``, exports a
383  
-``cache`` object that's automatically created from the ``CACHE_BACKEND``
384  
-setting::
  457
+The cache module, ``django.core.cache``, has a ``cache`` object that's
  458
+automatically created from the ``CACHE_BACKEND`` setting::
385 459
 
386 460
     >>> from django.core.cache import cache
387 461
 
@@ -396,15 +470,17 @@ argument in the ``CACHE_BACKEND`` setting (explained above).
396 470
 
397 471
 If the object doesn't exist in the cache, ``cache.get()`` returns ``None``::
398 472
 
399  
-    >>> cache.get('some_other_key')
400  
-    None
401  
-
402 473
     # Wait 30 seconds for 'my_key' to expire...
403 474
 
404 475
     >>> cache.get('my_key')
405 476
     None
406 477
 
407  
-get() can take a ``default`` argument::
  478
+We advise against storing the literal value ``None`` in the cache, because you
  479
+won't be able to distinguish between your stored ``None`` value and a cache
  480
+miss signified by a return value of ``None``.
  481
+
  482
+``cache.get()`` can take a ``default`` argument. This specifies which value to
  483
+return if the object doesn't exist in the cache::
408 484
 
409 485
     >>> cache.get('my_key', 'has expired')
410 486
     'has expired'
@@ -464,10 +540,7 @@ nonexistent cache key.::
464 540
     backends that support atomic increment/decrement (most notably, the
465 541
     memcached backend), increment and decrement operations will be atomic.
466 542
     However, if the backend doesn't natively provide an increment/decrement
467  
-    operation, it will be implemented using a 2 step retrieve/update.
468  
-
469  
-That's it. The cache has very few restrictions: You can cache any object that
470  
-can be pickled safely, although keys must be strings.
  543
+    operation, it will be implemented using a two-step retrieve/update.
471 544
 
472 545
 Upstream caches
473 546
 ===============
@@ -480,17 +553,20 @@ reaches your Web site.
480 553
 Here are a few examples of upstream caches:
481 554
 
482 555
     * Your ISP may cache certain pages, so if you requested a page from
483  
-      somedomain.com, your ISP would send you the page without having to access
484  
-      somedomain.com directly.
  556
+      http://example.com/, your ISP would send you the page without having to
  557
+      access example.com directly. The maintainers of example.com have no
  558
+      knowledge of this caching; the ISP sits between example.com and your Web
  559
+      browser, handling all of the caching transparently.
485 560
 
486  
-    * Your Django Web site may sit behind a Squid Web proxy
487  
-      (http://www.squid-cache.org/) that caches pages for performance. In this
488  
-      case, each request first would be handled by Squid, and it'd only be
489  
-      passed to your application if needed.
  561
+    * Your Django Web site may sit behind a *proxy cache*, such as Squid Web
  562
+      Proxy Cache (http://www.squid-cache.org/), that caches pages for
  563
+      performance. In this case, each request first would be handled by the
  564
+      proxy, and it would be passed to your application only if needed.
490 565
 
491  
-    * Your Web browser caches pages, too. If a Web page sends out the right
492  
-      headers, your browser will use the local (cached) copy for subsequent
493  
-      requests to that page.
  566
+    * Your Web browser caches pages, too. If a Web page sends out the
  567
+      appropriate headers, your browser will use the local cached copy for
  568
+      subsequent requests to that page, without even contacting the Web page
  569
+      again to see whether it has changed.
494 570
 
495 571
 Upstream caching is a nice efficiency boost, but there's a danger to it:
496 572
 Many Web pages' contents differ based on authentication and a host of other
@@ -503,30 +579,26 @@ cached your site, then the first user who logged in through that ISP would have
503 579
 his user-specific inbox page cached for subsequent visitors to the site. That's
504 580
 not cool.
505 581
 
506  
-Fortunately, HTTP provides a solution to this problem: A set of HTTP headers
507  
-exist to instruct caching mechanisms to differ their cache contents depending
508  
-on designated variables, and to tell caching mechanisms not to cache particular
509  
-pages.
  582
+Fortunately, HTTP provides a solution to this problem. A number of HTTP headers
  583
+exist to instruct upstream caches to differ their cache contents depending on
  584
+designated variables, and to tell caching mechanisms not to cache particular
  585
+pages. We'll look at some of these headers in the sections that follow.
510 586
 
511 587
 Using Vary headers
512 588
 ==================
513 589
 
514  
-One of these headers is ``Vary``. It defines which request headers a cache
  590
+The ``Vary`` header defines which request headers a cache
515 591
 mechanism should take into account when building its cache key. For example, if
516 592
 the contents of a Web page depend on a user's language preference, the page is
517 593
 said to "vary on language."
518 594
 
519 595
 By default, Django's cache system creates its cache keys using the requested
520  
-path -- e.g., ``"/stories/2005/jun/23/bank_robbed/"``. This means every request
  596
+path (e.g., ``"/stories/2005/jun/23/bank_robbed/"``). This means every request
521 597
 to that URL will use the same cached version, regardless of user-agent
522  
-differences such as cookies or language preferences.
523  
-
524  
-That's where ``Vary`` comes in.
525  
-
526  
-If your Django-powered page outputs different content based on some difference
527  
-in request headers -- such as a cookie, or language, or user-agent -- you'll
528  
-need to use the ``Vary`` header to tell caching mechanisms that the page output
529  
-depends on those things.
  598
+differences such as cookies or language preferences. However, if this page
  599
+produces different content based on some difference in request headers -- such
  600
+as a cookie, or a language, or a user-agent -- you'll need to use the ``Vary``
  601
+header to tell caching mechanisms that the page output depends on those things.
530 602
 
531 603
 To do this in Django, use the convenient ``vary_on_headers`` view decorator,
532 604
 like so::
@@ -535,54 +607,62 @@ like so::
535 607
 
536 608
     # Python 2.3 syntax.
537 609
     def my_view(request):
538  
-        ...
  610
+        # ...
539 611
     my_view = vary_on_headers(my_view, 'User-Agent')
540 612
 
541  
-    # Python 2.4 decorator syntax.
  613
+    # Python 2.4+ decorator syntax.
542 614
     @vary_on_headers('User-Agent')
543 615
     def my_view(request):
544  
-        ...
  616
+        # ...
545 617
 
546 618
 In this case, a caching mechanism (such as Django's own cache middleware) will
547 619
 cache a separate version of the page for each unique user-agent.
548 620
 
549 621
 The advantage to using the ``vary_on_headers`` decorator rather than manually
550 622
 setting the ``Vary`` header (using something like
551  
-``response['Vary'] = 'user-agent'``) is that the decorator adds to the ``Vary``
552  
-header (which may already exist) rather than setting it from scratch.
  623
+``response['Vary'] = 'user-agent'``) is that the decorator *adds* to the
  624
+``Vary`` header (which may already exist), rather than setting it from scratch
  625
+and potentially overriding anything that was already in there.
553 626
 
554 627
 You can pass multiple headers to ``vary_on_headers()``::
555 628
 
556 629
     @vary_on_headers('User-Agent', 'Cookie')
557 630
     def my_view(request):
558  
-        ...
  631
+        # ...
559 632
 
560  
-Because varying on cookie is such a common case, there's a ``vary_on_cookie``
  633
+This tells upstream caches to vary on *both*, which means each combination of
  634
+user-agent and cookie will get its own cache value. For example, a request with
  635
+the user-agent ``Mozilla`` and the cookie value ``foo=bar`` will be considered
  636
+different from a request with the user-agent ``Mozilla`` and the cookie value
  637
+``foo=ham``.
  638
+
  639
+Because varying on cookie is so common, there's a ``vary_on_cookie``
561 640
 decorator. These two views are equivalent::
562 641
 
563 642
     @vary_on_cookie
564 643
     def my_view(request):
565  
-        ...
  644
+        # ...
566 645
 
567 646
     @vary_on_headers('Cookie')
568 647
     def my_view(request):
569  
-        ...
  648
+        # ...
570 649
 
571  
-Also note that the headers you pass to ``vary_on_headers`` are not case
572  
-sensitive. ``"User-Agent"`` is the same thing as ``"user-agent"``.
  650
+The headers you pass to ``vary_on_headers`` are not case sensitive;
  651
+``"User-Agent"`` is the same thing as ``"user-agent"``.
573 652
 
574 653
 You can also use a helper function, ``django.utils.cache.patch_vary_headers``,
575  
-directly::
  654
+directly. This function sets, or adds to, the ``Vary header``. For example::
576 655
 
577 656
     from django.utils.cache import patch_vary_headers
  657
+
578 658
     def my_view(request):
579  
-        ...
  659
+        # ...
580 660
         response = render_to_response('template_name', context)
581 661
         patch_vary_headers(response, ['Cookie'])
582 662
         return response
583 663
 
584 664
 ``patch_vary_headers`` takes an ``HttpResponse`` instance as its first argument
585  
-and a list/tuple of header names as its second argument.
  665
+and a list/tuple of case-insensitive header names as its second argument.
586 666
 
587 667
 For more on Vary headers, see the `official Vary spec`_.
588 668
 
@@ -591,13 +671,13 @@ For more on Vary headers, see the `official Vary spec`_.
591 671
 Controlling cache: Using other headers
592 672
 ======================================
593 673
 
594  
-Another problem with caching is the privacy of data and the question of where
  674
+Other problems with caching are the privacy of data and the question of where
595 675
 data should be stored in a cascade of caches.
596 676
 
597  
-A user usually faces two kinds of caches: his own browser cache (a private
598  
-cache) and his provider's cache (a public cache). A public cache is used by
599  
-multiple users and controlled by someone else. This poses problems with
600  
-sensitive data: You don't want, say, your banking-account number stored in a
  677
+A user usually faces two kinds of caches: his or her own browser cache (a
  678
+private cache) and his or her provider's cache (a public cache). A public cache
  679
+is used by multiple users and controlled by someone else. This poses problems
  680
+with sensitive data--you don't want, say, your bank account number stored in a
601 681
 public cache. So Web applications need a way to tell caches which data is
602 682
 private and which is public.
603 683
 
@@ -605,9 +685,10 @@ The solution is to indicate a page's cache should be "private." To do this in
605 685
 Django, use the ``cache_control`` view decorator. Example::
606 686
 
607 687
     from django.views.decorators.cache import cache_control
  688
+
608 689
     @cache_control(private=True)
609 690
     def my_view(request):
610  
-        ...
  691
+        # ...
611 692
 
612 693
 This decorator takes care of sending out the appropriate HTTP header behind the
613 694
 scenes.
@@ -616,19 +697,21 @@ There are a few other ways to control cache parameters. For example, HTTP
616 697
 allows applications to do the following:
617 698
 
618 699
     * Define the maximum time a page should be cached.
  700
+
619 701
     * Specify whether a cache should always check for newer versions, only
620 702
       delivering the cached content when there are no changes. (Some caches
621  
-      might deliver cached content even if the server page changed -- simply
  703
+      might deliver cached content even if the server page changed, simply
622 704
       because the cache copy isn't yet expired.)
623 705
 
624 706
 In Django, use the ``cache_control`` view decorator to specify these cache
625 707
 parameters. In this example, ``cache_control`` tells caches to revalidate the
626  
-cache on every access and to store cached versions for, at most, 3600 seconds::
  708
+cache on every access and to store cached versions for, at most, 3,600 seconds::
627 709
 
628 710
     from django.views.decorators.cache import cache_control
  711
+
629 712
     @cache_control(must_revalidate=True, max_age=3600)
630 713
     def my_view(request):
631  
-        ...
  714
+        # ...
632 715
 
633 716
 Any valid ``Cache-Control`` HTTP directive is valid in ``cache_control()``.
634 717
 Here's a full list:
@@ -651,12 +734,14 @@ precedence, and the header values will be merged correctly.)
651 734
 
652 735
 If you want to use headers to disable caching altogether,
653 736
 ``django.views.decorators.cache.never_cache`` is a view decorator that adds
654  
-headers to ensure the response won't be cached by browsers or other caches. Example::
  737
+headers to ensure the response won't be cached by browsers or other caches.
  738
+Example::
655 739
 
656 740
     from django.views.decorators.cache import never_cache
  741
+
657 742
     @never_cache
658 743
     def myview(request):
659  
-        ...
  744
+        # ...
660 745
 
661 746
 .. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
662 747
 
@@ -667,11 +752,11 @@ Django comes with a few other pieces of middleware that can help optimize your
667 752
 apps' performance:
668 753
 
669 754
     * ``django.middleware.http.ConditionalGetMiddleware`` adds support for
670  
-      conditional GET. This makes use of ``ETag`` and ``Last-Modified``
671  
-      headers.
  755
+      modern browsers to conditionally GET responses based on the ``ETag`` 
  756
+      and ``Last-Modified`` headers.
672 757
 
673  
-    * ``django.middleware.gzip.GZipMiddleware`` compresses content for browsers
674  
-      that understand gzip compression (all modern browsers).
  758
+    * ``django.middleware.gzip.GZipMiddleware`` compresses responses for all 
  759
+      moderns browsers, saving bandwidth and transfer time.
675 760
 
676 761
 Order of MIDDLEWARE_CLASSES
677 762
 ===========================

0 notes on commit 957c721

Please sign in to comment.
Something went wrong with that request. Please try again.