summaryrefslogtreecommitdiff
path: root/parts/django/docs/topics/conditional-view-processing.txt
diff options
context:
space:
mode:
Diffstat (limited to 'parts/django/docs/topics/conditional-view-processing.txt')
-rw-r--r--parts/django/docs/topics/conditional-view-processing.txt199
1 files changed, 0 insertions, 199 deletions
diff --git a/parts/django/docs/topics/conditional-view-processing.txt b/parts/django/docs/topics/conditional-view-processing.txt
deleted file mode 100644
index c631a13..0000000
--- a/parts/django/docs/topics/conditional-view-processing.txt
+++ /dev/null
@@ -1,199 +0,0 @@
-===========================
-Conditional View Processing
-===========================
-
-.. versionadded:: 1.1
-
-HTTP clients can send a number of headers to tell the server about copies of a
-resource that they have already seen. This is commonly used when retrieving a
-Web page (using an HTTP ``GET`` request) to avoid sending all the data for
-something the client has already retrieved. However, the same headers can be
-used for all HTTP methods (``POST``, ``PUT``, ``DELETE``, etc).
-
-For each page (response) that Django sends back from a view, it might provide
-two HTTP headers: the ``ETag`` header and the ``Last-Modified`` header. These
-headers are optional on HTTP responses. They can be set by your view function,
-or you can rely on the :class:`~django.middleware.common.CommonMiddleware`
-middleware to set the ``ETag`` header.
-
-When the client next requests the same resource, it might send along a header
-such as `If-modified-since`_, containing the date of the last modification
-time it was sent, or `If-none-match`_, containing the ``ETag`` it was sent.
-If the current version of the page matches the ``ETag`` sent by the client, or
-if the resource has not been modified, a 304 status code can be sent back,
-instead of a full response, telling the client that nothing has changed.
-
-.. _If-none-match: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26
-.. _If-modified-since: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25
-
-When you need more fine-grained control you may use per-view conditional
-processing functions.
-
-.. conditional-decorators:
-
-The ``condition`` decorator
-===========================
-
-Sometimes (in fact, quite often) you can create functions to rapidly compute the ETag_
-value or the last-modified time for a resource, **without** needing to do all
-the computations needed to construct the full view. Django can then use these
-functions to provide an "early bailout" option for the view processing.
-Telling the client that the content has not been modified since the last
-request, perhaps.
-
-.. _ETag: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.11
-
-These two functions are passed as parameters the
-``django.views.decorators.http.condition`` decorator. This decorator uses
-the two functions (you only need to supply one, if you can't compute both
-quantities easily and quickly) to work out if the headers in the HTTP request
-match those on the resource. If they don't match, a new copy of the resource
-must be computed and your normal view is called.
-
-The ``condition`` decorator's signature looks like this::
-
- condition(etag_func=None, last_modified_func=None)
-
-The two functions, to compute the ETag and the last modified time, will be
-passed the incoming ``request`` object and the same parameters, in the same
-order, as the view function they are helping to wrap. The function passed
-``last_modified_func`` should return a standard datetime value specifying the
-last time the resource was modified, or ``None`` if the resource doesn't
-exist. The function passed to the ``etag`` decorator should return a string
-representing the `Etag`_ for the resource, or ``None`` if it doesn't exist.
-
-Using this feature usefully is probably best explained with an example.
-Suppose you have this pair of models, representing a simple blog system::
-
- import datetime
- from django.db import models
-
- class Blog(models.Model):
- ...
-
- class Entry(models.Model):
- blog = models.ForeignKey(Blog)
- published = models.DateTimeField(default=datetime.datetime.now)
- ...
-
-If the front page, displaying the latest blog entries, only changes when you
-add a new blog entry, you can compute the last modified time very quickly. You
-need the latest ``published`` date for every entry associated with that blog.
-One way to do this would be::
-
- def latest_entry(request, blog_id):
- return Entry.objects.filter(blog=blog_id).latest("published").published
-
-You can then use this function to provide early detection of an unchanged page
-for your front page view::
-
- from django.views.decorators.http import condition
-
- @condition(last_modified_func=latest_entry)
- def front_page(request, blog_id):
- ...
-
-Shortcuts for only computing one value
-======================================
-
-As a general rule, if you can provide functions to compute *both* the ETag and
-the last modified time, you should do so. You don't know which headers any
-given HTTP client will send you, so be prepared to handle both. However,
-sometimes only one value is easy to compute and Django provides decorators
-that handle only ETag or only last-modified computations.
-
-The ``django.views.decorators.http.etag`` and
-``django.views.decorators.http.last_modified`` decorators are passed the same
-type of functions as the ``condition`` decorator. Their signatures are::
-
- etag(etag_func)
- last_modified(last_modified_func)
-
-We could write the earlier example, which only uses a last-modified function,
-using one of these decorators::
-
- @last_modified(latest_entry)
- def front_page(request, blog_id):
- ...
-
-...or::
-
- def front_page(request, blog_id):
- ...
- front_page = last_modified(latest_entry)(front_page)
-
-Use ``condition`` when testing both conditions
-------------------------------------------------
-
-It might look nicer to some people to try and chain the ``etag`` and
-``last_modified`` decorators if you want to test both preconditions. However,
-this would lead to incorrect behavior.
-
-::
-
- # Bad code. Don't do this!
- @etag(etag_func)
- @last_modified(last_modified_func)
- def my_view(request):
- # ...
-
- # End of bad code.
-
-The first decorator doesn't know anything about the second and might
-answer that the response is not modified even if the second decorators would
-determine otherwise. The ``condition`` decorator uses both callback functions
-simultaneously to work out the right action to take.
-
-Using the decorators with other HTTP methods
-============================================
-
-The ``condition`` decorator is useful for more than only ``GET`` and
-``HEAD`` requests (``HEAD`` requests are the same as ``GET`` in this
-situation). It can be used also to be used to provide checking for ``POST``,
-``PUT`` and ``DELETE`` requests. In these situations, the idea isn't to return
-a "not modified" response, but to tell the client that the resource they are
-trying to change has been altered in the meantime.
-
-For example, consider the following exchange between the client and server:
-
- 1. Client requests ``/foo/``.
- 2. Server responds with some content with an ETag of ``"abcd1234"``.
- 3. Client sends an HTTP ``PUT`` request to ``/foo/`` to update the
- resource. It also sends an ``If-Match: "abcd1234"`` header to specify
- the version it is trying to update.
- 4. Server checks to see if the resource has changed, by computing the ETag
- the same way it does for a ``GET`` request (using the same function).
- If the resource *has* changed, it will return a 412 status code code,
- meaning "precondition failed".
- 5. Client sends a ``GET`` request to ``/foo/``, after receiving a 412
- response, to retrieve an updated version of the content before updating
- it.
-
-The important thing this example shows is that the same functions can be used
-to compute the ETag and last modification values in all situations. In fact,
-you **should** use the same functions, so that the same values are returned
-every time.
-
-Comparison with middleware conditional processing
-=================================================
-
-You may notice that Django already provides simple and straightforward
-conditional ``GET`` handling via the
-:class:`django.middleware.http.ConditionalGetMiddleware` and
-:class:`~django.middleware.common.CommonMiddleware`. Whilst certainly being
-easy to use and suitable for many situations, those pieces of middleware
-functionality have limitations for advanced usage:
-
- * They are applied globally to all views in your project
- * They don't save you from generating the response itself, which may be
- expensive
- * They are only appropriate for HTTP ``GET`` requests.
-
-You should choose the most appropriate tool for your particular problem here.
-If you have a way to compute ETags and modification times quickly and if some
-view takes a while to generate the content, you should consider using the
-``condition`` decorator described in this document. If everything already runs
-fairly quickly, stick to using the middleware and the amount of network
-traffic sent back to the clients will still be reduced if the view hasn't
-changed.
-