summaryrefslogtreecommitdiff
path: root/docs/topics
diff options
context:
space:
mode:
authorChris Cahoon <chris.cahoon@gmail.com>2009-06-25 15:42:51 +0000
committerChris Cahoon <chris.cahoon@gmail.com>2009-06-25 15:42:51 +0000
commiteac54911f5df8a31377fecd37b2bf34f0afef169 (patch)
treee5028a9673b5cbc337f380a6c808816236932f7b /docs/topics
parent7acae8f4d8a8f191d46fbb16e8cb15f46644b2ca (diff)
[soc2009/http-wsgi-improvements] Merged up to 11103 from trunk.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/http-wsgi-improvements@11109 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs/topics')
-rw-r--r--docs/topics/db/queries.txt8
-rw-r--r--docs/topics/db/sql.txt46
-rw-r--r--docs/topics/forms/modelforms.txt22
-rw-r--r--docs/topics/generic-views.txt503
-rw-r--r--docs/topics/http/middleware.txt15
-rw-r--r--docs/topics/http/sessions.txt3
-rw-r--r--docs/topics/i18n.txt18
-rw-r--r--docs/topics/index.txt2
-rw-r--r--docs/topics/install.txt35
-rw-r--r--docs/topics/testing.txt12
10 files changed, 628 insertions, 36 deletions
diff --git a/docs/topics/db/queries.txt b/docs/topics/db/queries.txt
index 4aa54261c4..5e353b2ec3 100644
--- a/docs/topics/db/queries.txt
+++ b/docs/topics/db/queries.txt
@@ -278,7 +278,7 @@ For example, this returns the first 5 objects (``LIMIT 5``)::
This returns the sixth through tenth objects (``OFFSET 5 LIMIT 5``)::
>>> Entry.objects.all()[5:10]
-
+
Negative indexing (i.e. ``Entry.objects.all()[-1]``) is not supported.
Generally, slicing a ``QuerySet`` returns a new ``QuerySet`` -- it doesn't
@@ -945,11 +945,15 @@ in the :ref:`related objects reference <ref-models-relations>`.
Removes all objects from the related object set.
To assign the members of a related set in one fell swoop, just assign to it
-from any iterable object. Example::
+from any iterable object. The iterable can contain object instances, or just
+a list of primary key values. For example::
b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]
+In this example, ``e1`` and ``e2`` can be full Entry instances, or integer
+primary key values.
+
If the ``clear()`` method is available, any pre-existing objects will be
removed from the ``entry_set`` before all objects in the iterable (in this
case, a list) are added to the set. If the ``clear()`` method is *not*
diff --git a/docs/topics/db/sql.txt b/docs/topics/db/sql.txt
index 4352908909..9c534709ca 100644
--- a/docs/topics/db/sql.txt
+++ b/docs/topics/db/sql.txt
@@ -29,6 +29,45 @@ is required. For example::
return row
+.. _transactions-and-raw-sql:
+
+Transactions and raw SQL
+------------------------
+If you are using transaction decorators (such as ``commit_on_success``) to
+wrap your views and provide transaction control, you don't have to make a
+manual call to ``transaction.commit_unless_managed()`` -- you can manually
+commit if you want to, but you aren't required to, since the decorator will
+commit for you. However, if you don't manually commit your changes, you will
+need to manually mark the transaction as dirty, using
+``transaction.set_dirty()``::
+
+ @commit_on_success
+ def my_custom_sql_view(request, value):
+ from django.db import connection, transaction
+ cursor = connection.cursor()
+
+ # Data modifying operation
+ cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value])
+
+ # Since we modified data, mark the transaction as dirty
+ transaction.set_dirty()
+
+ # Data retrieval operation. This doesn't dirty the transaction,
+ # so no call to set_dirty() is required.
+ cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value])
+ row = cursor.fetchone()
+
+ return render_to_response('template.html', {'row': row})
+
+The call to ``set_dirty()`` is made automatically when you use the Django ORM
+to make data modifying database calls. However, when you use raw SQL, Django
+has no way of knowing if your SQL modifies data or not. The manual call to
+``set_dirty()`` ensures that Django knows that there are modifications that
+must be committed.
+
+Connections and cursors
+-----------------------
+
``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_
(except when it comes to :ref:`transaction handling <topics-db-transactions>`).
If you're not familiar with the Python DB-API, note that the SQL statement in
@@ -39,9 +78,12 @@ necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the
``"?"`` placeholder, which is used by the SQLite Python bindings. This is for
the sake of consistency and sanity.)
+An easier option?
+-----------------
+
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
-use the ``where``, ``tables`` and ``params`` arguments to the standard lookup
-API.
+use the ``where``, ``tables`` and ``params`` arguments to the
+:ref:`extra clause <extra>` in the standard queryset API.
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
diff --git a/docs/topics/forms/modelforms.txt b/docs/topics/forms/modelforms.txt
index 690ca7f391..add581268b 100644
--- a/docs/topics/forms/modelforms.txt
+++ b/docs/topics/forms/modelforms.txt
@@ -397,16 +397,26 @@ to be rendered first, we could specify the following ``ModelForm``::
... model = Book
... fields = ['title', 'author']
+.. _overriding-modelform-clean-method:
Overriding the clean() method
-----------------------------
You can override the ``clean()`` method on a model form to provide additional
-validation in the same way you can on a normal form. However, by default the
-``clean()`` method validates the uniqueness of fields that are marked as
-``unique``, ``unique_together`` or ``unique_for_date|month|year`` on the model.
-Therefore, if you would like to override the ``clean()`` method and maintain the
-default validation, you must call the parent class's ``clean()`` method.
+validation in the same way you can on a normal form.
+
+In this regard, model forms have two specific characteristics when compared to
+forms:
+
+By default the ``clean()`` method validates the uniqueness of fields that are
+marked as ``unique``, ``unique_together`` or ``unique_for_date|month|year`` on
+the model. Therefore, if you would like to override the ``clean()`` method and
+maintain the default validation, you must call the parent class's ``clean()``
+method.
+
+Also, a model form instance bound to a model object will contain a
+``self.instance`` attribute that gives model form methods access to that
+specific model instance.
Form inheritance
----------------
@@ -611,7 +621,7 @@ Just like with ``ModelForms``, by default the ``clean()`` method of a
the unique constraints on your model (either ``unique``, ``unique_together`` or
``unique_for_date|month|year``). If you want to overide the ``clean()`` method
on a ``model_formset`` and maintain this validation, you must call the parent
-classes ``clean`` method::
+class's ``clean`` method::
class MyModelFormSet(BaseModelFormSet):
def clean(self):
diff --git a/docs/topics/generic-views.txt b/docs/topics/generic-views.txt
new file mode 100644
index 0000000000..c7d751a86b
--- /dev/null
+++ b/docs/topics/generic-views.txt
@@ -0,0 +1,503 @@
+.. _topics-generic-views:
+
+=============
+Generic views
+=============
+
+Writing Web applications can be monotonous, because we repeat certain patterns
+again and again. Django tries to take away some of that monotony at the model
+and template layers, but Web developers also experience this boredom at the view
+level.
+
+Django's *generic views* were developed to ease that pain. They take certain
+common idioms and patterns found in view development and abstract them so that
+you can quickly write common views of data without having to write too much
+code.
+
+We can recognize certain common tasks, like displaying a list of objects, and
+write code that displays a list of *any* object. Then the model in question can
+be passed as an extra argument to the URLconf.
+
+Django ships with generic views to do the following:
+
+ * Perform common "simple" tasks: redirect to a different page and
+ render a given template.
+
+ * Display list and detail pages for a single object. If we were creating an
+ application to manage conferences then a ``talk_list`` view and a
+ ``registered_user_list`` view would be examples of list views. A single
+ talk page is an example of what we call a "detail" view.
+
+ * Present date-based objects in year/month/day archive pages,
+ associated detail, and "latest" pages. The Django Weblog's
+ (http://www.djangoproject.com/weblog/) year, month, and
+ day archives are built with these, as would be a typical
+ newspaper's archives.
+
+ * Allow users to create, update, and delete objects -- with or
+ without authorization.
+
+Taken together, these views provide easy interfaces to perform the most common
+tasks developers encounter.
+
+Using generic views
+===================
+
+All of these views are used by creating configuration dictionaries in
+your URLconf files and passing those dictionaries as the third member of the
+URLconf tuple for a given pattern.
+
+For example, here's a simple URLconf you could use to present a static "about"
+page::
+
+ from django.conf.urls.defaults import *
+ from django.views.generic.simple import direct_to_template
+
+ urlpatterns = patterns('',
+ ('^about/$', direct_to_template, {
+ 'template': 'about.html'
+ })
+ )
+
+Though this might seem a bit "magical" at first glance -- look, a view with no
+code! --, actually the ``direct_to_template`` view simply grabs information from
+the extra-parameters dictionary and uses that information when rendering the
+view.
+
+Because this generic view -- and all the others -- is a regular view functions
+like any other, we can reuse it inside our own views. As an example, let's
+extend our "about" example to map URLs of the form ``/about/<whatever>/`` to
+statically rendered ``about/<whatever>.html``. We'll do this by first modifying
+the URLconf to point to a view function:
+
+.. parsed-literal::
+
+ from django.conf.urls.defaults import *
+ from django.views.generic.simple import direct_to_template
+ **from mysite.books.views import about_pages**
+
+ urlpatterns = patterns('',
+ ('^about/$', direct_to_template, {
+ 'template': 'about.html'
+ }),
+ **('^about/(\w+)/$', about_pages),**
+ )
+
+Next, we'll write the ``about_pages`` view::
+
+ from django.http import Http404
+ from django.template import TemplateDoesNotExist
+ from django.views.generic.simple import direct_to_template
+
+ def about_pages(request, page):
+ try:
+ return direct_to_template(request, template="about/%s.html" % page)
+ except TemplateDoesNotExist:
+ raise Http404()
+
+Here we're treating ``direct_to_template`` like any other function. Since it
+returns an ``HttpResponse``, we can simply return it as-is. The only slightly
+tricky business here is dealing with missing templates. We don't want a
+nonexistent template to cause a server error, so we catch
+``TemplateDoesNotExist`` exceptions and return 404 errors instead.
+
+.. admonition:: Is there a security vulnerability here?
+
+ Sharp-eyed readers may have noticed a possible security hole: we're
+ constructing the template name using interpolated content from the browser
+ (``template="about/%s.html" % page``). At first glance, this looks like a
+ classic *directory traversal* vulnerability. But is it really?
+
+ Not exactly. Yes, a maliciously crafted value of ``page`` could cause
+ directory traversal, but although ``page`` *is* taken from the request URL,
+ not every value will be accepted. The key is in the URLconf: we're using
+ the regular expression ``\w+`` to match the ``page`` part of the URL, and
+ ``\w`` only accepts letters and numbers. Thus, any malicious characters
+ (dots and slashes, here) will be rejected by the URL resolver before they
+ reach the view itself.
+
+Generic views of objects
+========================
+
+The ``direct_to_template`` certainly is useful, but Django's generic views
+really shine when it comes to presenting views on your database content. Because
+it's such a common task, Django comes with a handful of built-in generic views
+that make generating list and detail views of objects incredibly easy.
+
+Let's take a look at one of these generic views: the "object list" view. We'll
+be using these models::
+
+ # models.py
+ from django.db import models
+
+ class Publisher(models.Model):
+ name = models.CharField(max_length=30)
+ address = models.CharField(max_length=50)
+ city = models.CharField(max_length=60)
+ state_province = models.CharField(max_length=30)
+ country = models.CharField(max_length=50)
+ website = models.URLField()
+
+ def __unicode__(self):
+ return self.name
+
+ class Meta:
+ ordering = ["-name"]
+
+ class Book(models.Model):
+ title = models.CharField(max_length=100)
+ authors = models.ManyToManyField('Author')
+ publisher = models.ForeignKey(Publisher)
+ publication_date = models.DateField()
+
+To build a list page of all books, we'd use a URLconf along these lines::
+
+ from django.conf.urls.defaults import *
+ from django.views.generic import list_detail
+ from mysite.books.models import Publisher
+
+ publisher_info = {
+ "queryset" : Publisher.objects.all(),
+ }
+
+ urlpatterns = patterns('',
+ (r'^publishers/$', list_detail.object_list, publisher_info)
+ )
+
+That's all the Python code we need to write. We still need to write a template,
+however. We could explicitly tell the ``object_list`` view which template to use
+by including a ``template_name`` key in the extra arguments dictionary, but in
+the absence of an explicit template Django will infer one from the object's
+name. In this case, the inferred template will be
+``"books/publisher_list.html"`` -- the "books" part comes from the name of the
+app that defines the model, while the "publisher" bit is just the lowercased
+version of the model's name.
+
+.. highlightlang:: html+django
+
+This template will be rendered against a context containing a variable called
+``object_list`` that contains all the book objects. A very simple template
+might look like the following::
+
+ {% extends "base.html" %}
+
+ {% block content %}
+ <h2>Publishers</h2>
+ <ul>
+ {% for publisher in object_list %}
+ <li>{{ publisher.name }}</li>
+ {% endfor %}
+ </ul>
+ {% endblock %}
+
+That's really all there is to it. All the cool features of generic views come
+from changing the "info" dictionary passed to the generic view. The
+:ref:`generic views reference<ref-generic-views>` documents all the generic
+views and all their options in detail; the rest of this document will consider
+some of the common ways you might customize and extend generic views.
+
+Extending generic views
+=======================
+
+.. highlightlang:: python
+
+There's no question that using generic views can speed up development
+substantially. In most projects, however, there comes a moment when the
+generic views no longer suffice. Indeed, the most common question asked by new
+Django developers is how to make generic views handle a wider array of
+situations.
+
+Luckily, in nearly every one of these cases, there are ways to simply extend
+generic views to handle a larger array of use cases. These situations usually
+fall into a handful of patterns dealt with in the sections that follow.
+
+Making "friendly" template contexts
+-----------------------------------
+
+You might have noticed that our sample publisher list template stores all the
+books in a variable named ``object_list``. While this works just fine, it isn't
+all that "friendly" to template authors: they have to "just know" that they're
+dealing with books here. A better name for that variable would be
+``publisher_list``; that variable's content is pretty obvious.
+
+We can change the name of that variable easily with the ``template_object_name``
+argument:
+
+.. parsed-literal::
+
+ publisher_info = {
+ "queryset" : Publisher.objects.all(),
+ **"template_object_name" : "publisher",**
+ }
+
+ urlpatterns = patterns('',
+ (r'^publishers/$', list_detail.object_list, publisher_info)
+ )
+
+Providing a useful ``template_object_name`` is always a good idea. Your
+coworkers who design templates will thank you.
+
+Adding extra context
+--------------------
+
+Often you simply need to present some extra information beyond that provided by
+the generic view. For example, think of showing a list of all the other
+publishers on each publisher detail page. The ``object_detail`` generic view
+provides the publisher to the context, but it seems there's no way to get a list
+of *all* publishers in that template.
+
+But there is: all generic views take an extra optional parameter,
+``extra_context``. This is a dictionary of extra objects that will be added to
+the template's context. So, to provide the list of all publishers on the detail
+detail view, we'd use an info dict like this:
+
+.. parsed-literal::
+
+ from mysite.books.models import Publisher, **Book**
+
+ publisher_info = {
+ "queryset" : Publisher.objects.all(),
+ "template_object_name" : "publisher",
+ **"extra_context" : {"book_list" : Book.objects.all()}**
+ }
+
+This would populate a ``{{ book_list }}`` variable in the template context.
+This pattern can be used to pass any information down into the template for the
+generic view. It's very handy.
+
+However, there's actually a subtle bug here -- can you spot it?
+
+The problem has to do with when the queries in ``extra_context`` are evaluated.
+Because this example puts ``Publisher.objects.all()`` in the URLconf, it will
+be evaluated only once (when the URLconf is first loaded). Once you add or
+remove publishers, you'll notice that the generic view doesn't reflect those
+changes until you reload the Web server (see :ref:`caching-and-querysets`
+for more information about when QuerySets are cached and evaluated).
+
+.. note::
+
+ This problem doesn't apply to the ``queryset`` generic view argument. Since
+ Django knows that particular QuerySet should *never* be cached, the generic
+ view takes care of clearing the cache when each view is rendered.
+
+The solution is to use a callback in ``extra_context`` instead of a value. Any
+callable (i.e., a function) that's passed to ``extra_context`` will be evaluated
+when the view is rendered (instead of only once). You could do this with an
+explicitly defined function:
+
+.. parsed-literal::
+
+ def get_books():
+ return Book.objects.all()
+
+ publisher_info = {
+ "queryset" : Publisher.objects.all(),
+ "template_object_name" : "publisher",
+ "extra_context" : **{"book_list" : get_books}**
+ }
+
+or you could use a less obvious but shorter version that relies on the fact that
+``Book.objects.all`` is itself a callable:
+
+.. parsed-literal::
+
+ publisher_info = {
+ "queryset" : Publisher.objects.all(),
+ "template_object_name" : "publisher",
+ "extra_context" : **{"book_list" : Book.objects.all}**
+ }
+
+Notice the lack of parentheses after ``Book.objects.all``; this references
+the function without actually calling it (which the generic view will do later).
+
+Viewing subsets of objects
+--------------------------
+
+Now let's take a closer look at this ``queryset`` key we've been using all
+along. Most generic views take one of these ``queryset`` arguments -- it's how
+the view knows which set of objects to display (see :ref:`topics-db-queries` for
+more information about ``QuerySet`` objects, and see the
+:ref:`generic views reference<ref-generic-views>` for the complete details).
+
+To pick a simple example, we might want to order a list of books by
+publication date, with the most recent first:
+
+.. parsed-literal::
+
+ book_info = {
+ "queryset" : Book.objects.all().order_by("-publication_date"),
+ }
+
+ urlpatterns = patterns('',
+ (r'^publishers/$', list_detail.object_list, publisher_info),
+ **(r'^books/$', list_detail.object_list, book_info),**
+ )
+
+
+That's a pretty simple example, but it illustrates the idea nicely. Of course,
+you'll usually want to do more than just reorder objects. If you want to
+present a list of books by a particular publisher, you can use the same
+technique:
+
+.. parsed-literal::
+
+ **acme_books = {**
+ **"queryset": Book.objects.filter(publisher__name="Acme Publishing"),**
+ **"template_name" : "books/acme_list.html"**
+ **}**
+
+ urlpatterns = patterns('',
+ (r'^publishers/$', list_detail.object_list, publisher_info),
+ **(r'^books/acme/$', list_detail.object_list, acme_books),**
+ )
+
+Notice that along with a filtered ``queryset``, we're also using a custom
+template name. If we didn't, the generic view would use the same template as the
+"vanilla" object list, which might not be what we want.
+
+Also notice that this isn't a very elegant way of doing publisher-specific
+books. If we want to add another publisher page, we'd need another handful of
+lines in the URLconf, and more than a few publishers would get unreasonable.
+We'll deal with this problem in the next section.
+
+.. note::
+
+ If you get a 404 when requesting ``/books/acme/``, check to ensure you
+ actually have a Publisher with the name 'ACME Publishing'. Generic
+ views have an ``allow_empty`` parameter for this case. See the
+ :ref:`generic views reference<ref-generic-views>` for more details.
+
+Complex filtering with wrapper functions
+----------------------------------------
+
+Another common need is to filter down the objects given in a list page by some
+key in the URL. Earlier we hard-coded the publisher's name in the URLconf, but
+what if we wanted to write a view that displayed all the books by some arbitrary
+publisher? We can "wrap" the ``object_list`` generic view to avoid writing a lot
+of code by hand. As usual, we'll start by writing a URLconf:
+
+.. parsed-literal::
+
+ from mysite.books.views import books_by_publisher
+
+ urlpatterns = patterns('',
+ (r'^publishers/$', list_detail.object_list, publisher_info),
+ **(r'^books/(\w+)/$', books_by_publisher),**
+ )
+
+Next, we'll write the ``books_by_publisher`` view itself::
+
+ from django.http import Http404
+ from django.views.generic import list_detail
+ from mysite.books.models import Book, Publisher
+
+ def books_by_publisher(request, name):
+
+ # Look up the publisher (and raise a 404 if it can't be found).
+ try:
+ publisher = Publisher.objects.get(name__iexact=name)
+ except Publisher.DoesNotExist:
+ raise Http404
+
+ # Use the object_list view for the heavy lifting.
+ return list_detail.object_list(
+ request,
+ queryset = Book.objects.filter(publisher=publisher),
+ template_name = "books/books_by_publisher.html",
+ template_object_name = "books",
+ extra_context = {"publisher" : publisher}
+ )
+
+This works because there's really nothing special about generic views -- they're
+just Python functions. Like any view function, generic views expect a certain
+set of arguments and return ``HttpResponse`` objects. Thus, it's incredibly easy
+to wrap a small function around a generic view that does additional work before
+(or after; see the next section) handing things off to the generic view.
+
+.. note::
+
+ Notice that in the preceding example we passed the current publisher being
+ displayed in the ``extra_context``. This is usually a good idea in wrappers
+ of this nature; it lets the template know which "parent" object is currently
+ being browsed.
+
+Performing extra work
+---------------------
+
+The last common pattern we'll look at involves doing some extra work before
+or after calling the generic view.
+
+Imagine we had a ``last_accessed`` field on our ``Author`` object that we were
+using to keep track of the last time anybody looked at that author::
+
+ # models.py
+
+ class Author(models.Model):
+ salutation = models.CharField(max_length=10)
+ first_name = models.CharField(max_length=30)
+ last_name = models.CharField(max_length=40)
+ email = models.EmailField()
+ headshot = models.ImageField(upload_to='/tmp')
+ last_accessed = models.DateTimeField()
+
+The generic ``object_detail`` view, of course, wouldn't know anything about this
+field, but once again we could easily write a custom view to keep that field
+updated.
+
+First, we'd need to add an author detail bit in the URLconf to point to a
+custom view:
+
+.. parsed-literal::
+
+ from mysite.books.views import author_detail
+
+ urlpatterns = patterns('',
+ #...
+ **(r'^authors/(?P<author_id>\d+)/$', author_detail),**
+ )
+
+Then we'd write our wrapper function::
+
+ import datetime
+ from mysite.books.models import Author
+ from django.views.generic import list_detail
+ from django.shortcuts import get_object_or_404
+
+ def author_detail(request, author_id):
+ # Look up the Author (and raise a 404 if she's not found)
+ author = get_object_or_404(Author, pk=author_id)
+
+ # Record the last accessed date
+ author.last_accessed = datetime.datetime.now()
+ author.save()
+
+ # Show the detail page
+ return list_detail.object_detail(
+ request,
+ queryset = Author.objects.all(),
+ object_id = author_id,
+ )
+
+.. note::
+
+ This code won't actually work unless you create a
+ ``books/author_detail.html`` template.
+
+We can use a similar idiom to alter the response returned by the generic view.
+If we wanted to provide a downloadable plain-text version of the list of
+authors, we could use a view like this::
+
+ def author_list_plaintext(request):
+ response = list_detail.object_list(
+ request,
+ queryset = Author.objects.all(),
+ mimetype = "text/plain",
+ template_name = "books/author_list.txt"
+ )
+ response["Content-Disposition"] = "attachment; filename=authors.txt"
+ return response
+
+This works because the generic views return simple ``HttpResponse`` objects
+that can be treated like dictionaries to set HTTP headers. This
+``Content-Disposition`` business, by the way, instructs the browser to
+download and save the page instead of displaying it in the browser.
diff --git a/docs/topics/http/middleware.txt b/docs/topics/http/middleware.txt
index 9040533f33..19facb8371 100644
--- a/docs/topics/http/middleware.txt
+++ b/docs/topics/http/middleware.txt
@@ -107,15 +107,18 @@ middleware is always called on every response.
``request`` is an :class:`~django.http.HttpRequest` object. ``response`` is the
:class:`~django.http. HttpResponse` object returned by a Django view.
-``process_response()`` should return an :class:`~django.http. HttpResponse`
+``process_response()`` must return an :class:`~django.http. HttpResponse`
object. It could alter the given ``response``, or it could create and return a
brand-new :class:`~django.http. HttpResponse`.
-Remember that your middleware will not be called if another middleware object
-returns a response before you. But unlike ``process_request()`` and
-``process_view()``, during the response phase the classes are applied in reverse
-order, from the bottom up. This means classes defined at the end of
-:setting:`MIDDLEWARE_CLASSES` will be run first.
+Unlike the ``process_request()`` and ``process_view()`` methods, the
+``process_response()`` method is always called, even if the ``process_request()``
+and ``process_view()`` methods of the same middleware class were skipped because
+an earlier middleware method returned an :class:`~django.http. HttpResponse`
+(this means that your ``process_response()`` method cannot rely on setup done in
+``process_request()``, for example). In addition, during the response phase the
+classes are applied in reverse order, from the bottom up. This means classes
+defined at the end of :setting:`MIDDLEWARE_CLASSES` will be run first.
.. _exception-middleware:
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index fa3864a7c2..d3956504c7 100644
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -4,6 +4,9 @@
How to use sessions
===================
+.. module:: django.contrib.sessions
+ :synopsis: Provides session management for Django projects.
+
Django provides full support for anonymous sessions. The session framework lets
you store and retrieve arbitrary data on a per-site-visitor basis. It stores
data on the server side and abstracts the sending and receiving of cookies.
diff --git a/docs/topics/i18n.txt b/docs/topics/i18n.txt
index 140adce74c..86c03221aa 100644
--- a/docs/topics/i18n.txt
+++ b/docs/topics/i18n.txt
@@ -978,15 +978,17 @@ message files (``.po``). Translation work itself just involves editing existing
files of this type, but if you want to create your own message files, or want to
test or compile a changed message file, you will need the ``gettext`` utilities:
- * Download the following zip files from
- http://sourceforge.net/projects/gettext
+ * Download the following zip files from the GNOME servers
+ http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/ or from one
+ of its mirrors_
- * ``gettext-runtime-X.bin.woe32.zip``
- * ``gettext-tools-X.bin.woe32.zip``
- * ``libiconv-X.bin.woe32.zip``
+ * ``gettext-runtime-X.zip``
+ * ``gettext-tools-X.zip``
- * Extract the 3 files in the same folder (i.e. ``C:\Program
- Files\gettext-utils``)
+ ``X`` is the version number, we recomend using ``0.15`` or higher.
+
+ * Extract the contents of the ``bin\`` directories in both files to the
+ same folder on your system (i.e. ``C:\Program Files\gettext-utils``)
* Update the system PATH:
@@ -995,6 +997,8 @@ test or compile a changed message file, you will need the ``gettext`` utilities:
* Add ``;C:\Program Files\gettext-utils\bin`` at the end of the
``Variable value`` field
+.. _mirrors: http://ftp.gnome.org/pub/GNOME/MIRRORS
+
You may also use ``gettext`` binaries you have obtained elsewhere, so long as
the ``xgettext --version`` command works properly. Some version 0.14.4 binaries
have been found to not support this command. Do not attempt to use Django
diff --git a/docs/topics/index.txt b/docs/topics/index.txt
index 20d7aa3061..7fa283aa1a 100644
--- a/docs/topics/index.txt
+++ b/docs/topics/index.txt
@@ -14,6 +14,7 @@ Introductions to all the key parts of Django you'll need to know:
forms/index
forms/modelforms
templates
+ generic-views
files
testing
auth
@@ -25,3 +26,4 @@ Introductions to all the key parts of Django you'll need to know:
serialization
settings
signals
+
diff --git a/docs/topics/install.txt b/docs/topics/install.txt
index 4268759828..b66c8aef15 100644
--- a/docs/topics/install.txt
+++ b/docs/topics/install.txt
@@ -61,13 +61,27 @@ for each platform.
Get your database running
=========================
-If you plan to use Django's database API functionality, you'll need to
-make sure a database server is running. Django works with PostgreSQL_,
-MySQL_, Oracle_ and SQLite_ (although SQLite doesn't require a separate server
-to be running).
+If you plan to use Django's database API functionality, you'll need to make
+sure a database server is running. Django supports many different database
+servers and is officially supported with PostgreSQL_, MySQL_, Oracle_ and
+SQLite_ (although SQLite doesn't require a separate server to be running).
-Additionally, you'll need to make sure your Python database bindings are
-installed.
+In addition to the officially supported databases, there are backends provided
+by 3rd parties that allow you to use other databases with Django:
+
+* `Sybase SQL Anywhere`_
+* `IBM DB2`_
+* `Microsoft SQL Server 2005`_
+* Firebird_
+* ODBC_
+
+The Django versions and ORM features supported by these unofficial backends
+vary considerably. Queries regarding the specific capabilities of these
+unofficial backends, along with any support queries, should be directed to the
+support channels provided by each 3rd party project.
+
+In addition to a database backend, you'll need to make sure your Python
+database bindings are installed.
* If you're using PostgreSQL, you'll need the psycopg_ package. Django supports
both version 1 and 2. (When you configure Django's database layer, specify
@@ -89,6 +103,9 @@ installed.
:ref:`Oracle backend <oracle-notes>` for important information
regarding supported versions of both Oracle and ``cx_Oracle``.
+* If you're using an unofficial 3rd party backend, please consult the
+ documentation provided for any additional requirements.
+
If you plan to use Django's ``manage.py syncdb`` command to
automatically create database tables for your models, you'll need to
ensure that Django has permission to create and alter tables in the
@@ -111,7 +128,11 @@ Django will need permission to create a test database.
.. _pysqlite: http://pysqlite.org/
.. _cx_Oracle: http://cx-oracle.sourceforge.net/
.. _Oracle: http://www.oracle.com/
-
+.. _Sybase SQL Anywhere: http://code.google.com/p/sqlany-django/
+.. _IBM DB2: http://code.google.com/p/ibm-db/
+.. _Microsoft SQL Server 2005: http://code.google.com/p/django-mssql/
+.. _Firebird: http://code.google.com/p/django-firebird/
+.. _ODBC: http://code.google.com/p/django-pyodbc/
.. _removing-old-versions-of-django:
Remove any old versions of Django
diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt
index 0410049297..1256a61187 100644
--- a/docs/topics/testing.txt
+++ b/docs/topics/testing.txt
@@ -139,8 +139,8 @@ In the case of model tests, note that the test runner takes care of creating
its own test database. That is, any test that accesses a database -- by
creating and saving model instances, for example -- will not affect your
production database. However, the database is not refreshed between doctests,
-so if your doctest requires a certain state you should consider flushin the
-database or loading a fixture. (See the section on fixtures, below, for more
+so if your doctest requires a certain state you should consider flushing the
+database or loading a fixture. (See the section on fixtures, below, for more
on this.) Note that to use this feature, the database user Django is connecting
as must have ``CREATE DATABASE`` rights.
@@ -1042,7 +1042,7 @@ applications:
Asserts that a ``Response`` instance produced the given ``status_code`` and
that ``text`` does not appears in the content of the response.
-.. method:: assertFormError(response, form, field, errors)
+.. method:: TestCase.assertFormError(response, form, field, errors)
Asserts that a field on a form raises the provided list of errors when
rendered on the form.
@@ -1057,19 +1057,19 @@ applications:
``errors`` is an error string, or a list of error strings, that are
expected as a result of form validation.
-.. method:: assertTemplateUsed(response, template_name)
+.. method:: TestCase.assertTemplateUsed(response, template_name)
Asserts that the template with the given name was used in rendering the
response.
The name is a string such as ``'admin/index.html'``.
-.. method:: assertTemplateNotUsed(response, template_name)
+.. method:: TestCase.assertTemplateNotUsed(response, template_name)
Asserts that the template with the given name was *not* used in rendering
the response.
-.. method:: assertRedirects(response, expected_url, status_code=302, target_status_code=200)
+.. method:: TestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200)
Asserts that the response return a ``status_code`` redirect status, it
redirected to ``expected_url`` (including any GET data), and the final