1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

[soc2009/multidb] Merged up to trunk r11756.

git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11758 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Alex Gaynor
2009-11-21 06:55:11 +00:00
parent 2bc7422b52
commit e9e73c4b68
198 changed files with 5793 additions and 1878 deletions

View File

@@ -18,7 +18,7 @@ How do I get started?
What are Django's prerequisites?
--------------------------------
Django requires Python_, specifically any version of Python from 2.3
Django requires Python_, specifically any version of Python from 2.4
through 2.6. No other Python libraries are required for basic Django
usage.
@@ -42,30 +42,35 @@ PostgreSQL fans, and MySQL_, `SQLite 3`_, and Oracle_ are also supported.
.. _`SQLite 3`: http://www.sqlite.org/
.. _Oracle: http://www.oracle.com/
Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5?
----------------------------------------------------------------------------------------
Do I lose anything by using Python 2.4 versus newer Python versions, such as Python 2.5 or 2.6?
-----------------------------------------------------------------------------------------------
Not in the core framework. Currently, Django itself officially
supports any version of Python from 2.3 through 2.6,
inclusive. However, some add-on components may require a more recent
Python version; the ``django.contrib.gis`` component, for example,
requires at least Python 2.4, and third-party applications for use
with Django are, of course, free to set their own version
requirements.
Not in the core framework. Currently, Django itself officially supports any
version of Python from 2.4 through 2.6, inclusive. However, newer versions of
Python are often faster, have more features, and are better supported.
Third-party applications for use with Django are, of course, free to set their
own version requirements.
Please note, however, that over the next year or two Django will begin
dropping support for older Python versions as part of a migration
which will end with Django running on Python 3.0 (see next question
for details). So if you're just starting out with Python, it's
recommended that you use the latest 2.x release (currently, Python
2.6). This will let you take advantage of the numerous improvements
and optimizations to the Python language since version 2.3, and will
help ease the process of dropping support for older Python versions on
the road to Python 3.0.
Over the next year or two Django will begin dropping support for older Python
versions as part of a migration which will end with Django running on Python 3
(see below for details).
Can I use Django with Python 3.0?
All else being equal, we recommend that you use the latest 2.x release
(currently Python 2.6). This will let you take advantage of the numerous
improvements and optimizations to the Python language since version 2.4, and
will help ease the process of dropping support for older Python versions on
the road to Python 3.
Can I use Django with Python 2.3?
---------------------------------
Django 1.1 (and earlier) supported Python 2.3. Django 1.2 and newer does not.
We highly recommend you upgrade Python if at all possible, but Django 1.1 will
continue to work on Python 2.3.
Can I use Django with Python 3?
-------------------------------
Not at the moment. Python 3.0 introduced a number of
backwards-incompatible changes to the Python language, and although
these changes are generally a good thing for Python's future, it will

View File

@@ -202,7 +202,5 @@ The Django open-source project
* **Django over time:**
:ref:`API stability <misc-api-stability>` |
:ref:`Archive of release notes <releases-index>` | `Backwards-incompatible changes`_ |
:ref:`Release notes <releases-index>` |
:ref:`Deprecation Timeline <internals-deprecation>`
.. _Backwards-incompatible changes: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges

View File

@@ -148,7 +148,6 @@ Joseph Kocherhans
.. _brian rosner: http://oebfare.com/
.. _eldarion: http://eldarion.com/
.. _pinax: http://pinaxproject.com/
.. _django dose: http://djangodose.com/
`Gary Wilson`_
@@ -189,6 +188,31 @@ Karen Tracey
Karen lives in Apex, NC, USA.
`Jannis Leidel`_
Jannis graduated in media design from `Bauhaus-University Weimar`_,
is the author of a number of pluggable Django apps and likes to
contribute to Open Source projects like Pinax_. He currently works as
a freelance web developer and designer.
Jannis lives in Berlin, Germany.
.. _Jannis Leidel: http://jezdez.com/
.. _Bauhaus-University Weimar: http://www.uni-weimar.de/
.. _pinax: http://pinaxproject.com/
`James Tauber`_
James is the lead developer of Pinax_ and the CEO and founder of
Eldarion_. He has been doing open source software since 1993, Python
since 1998 and Django since 2006. He serves on the board of the Python
Software Foundation and is currently on a leave of absence from a PhD in
linguistics.
James currently lives in Boston, MA, USA but originally hails from
Perth, Western Australia where he attended the same high school as
Russell Keith-Magee.
.. _James Tauber: http://jtauber.com/
Specialists
-----------

View File

@@ -13,6 +13,21 @@ their deprecation, as per the :ref:`Django deprecation policy
hooking up admin URLs. This has been deprecated since the 1.1
release.
* 1.4
* ``CsrfResponseMiddleware``. This has been deprecated since the 1.2
release, in favour of the template tag method for inserting the CSRF
token. ``CsrfMiddleware``, which combines ``CsrfResponseMiddleware``
and ``CsrfViewMiddleware``, is also deprecated.
* The old imports for CSRF functionality (``django.contrib.csrf.*``),
which moved to core in 1.2, will be removed.
* ``SMTPConnection``. The 1.2 release deprecated the ``SMTPConnection``
class in favor of a generic E-mail backend API.
* The many to many SQL generation functions on the database backends
will be removed. These have been deprecated since the 1.2 release.
* 2.0
* ``django.views.defaults.shortcut()``. This function has been moved
to ``django.contrib.contenttypes.views.shortcut()`` as part of the

View File

@@ -56,7 +56,7 @@ These releases will contain new features, improvements to existing features, and
such. A minor release may deprecate certain features from previous releases. If a
feature in version ``A.B`` is deprecated, it will continue to work in version
``A.B+1``. In version ``A.B+2``, use of the feature will raise a
``PendingDeprecationWarning`` but will continue to work. Version ``A.B+3`` will
``DeprecationWarning`` but will continue to work. Version ``A.B+3`` will
remove the feature entirely.
So, for example, if we decided to remove a function that existed in Django 1.0:

View File

@@ -12,7 +12,7 @@ Install Python
--------------
Being a Python Web framework, Django requires Python. It works with any Python
version from 2.3 to 2.6 (due to backwards
version from 2.4 to 2.6 (due to backwards
incompatibilities in Python 3.0, Django does not currently work with
Python 3.0; see :ref:`the Django FAQ <faq-install>` for more
information on supported Python versions and the 3.0 transition), but we recommend installing Python 2.5 or later. If you do so, you won't need to set up a database just yet: Python 2.5 or later includes a lightweight database called SQLite_.

View File

@@ -282,6 +282,7 @@ That'll create a directory :file:`polls`, which is laid out like this::
polls/
__init__.py
models.py
tests.py
views.py
This directory structure will house the poll application.

View File

@@ -34,11 +34,11 @@ activate the admin site for your installation, do these three things:
* Run ``python manage.py syncdb``. Since you have added a new application
to :setting:`INSTALLED_APPS`, the database tables need to be updated.
* Edit your ``mysite/urls.py`` file and uncomment the lines below the
"Uncomment the next two lines..." comment. This file is a URLconf;
we'll dig into URLconfs in the next tutorial. For now, all you need to
know is that it maps URL roots to applications. In the end, you should
have a ``urls.py`` file that looks like this:
* Edit your ``mysite/urls.py`` file and uncomment the lines that reference
the admin -- there are three lines in total to uncomment. This file is a
URLconf; we'll dig into URLconfs in the next tutorial. For now, all you
need to know is that it maps URL roots to applications. In the end, you
should have a ``urls.py`` file that looks like this:
.. versionchanged:: 1.1
The method for adding admin urls has changed in Django 1.1.

View File

@@ -171,15 +171,23 @@ and put the following Python code in it::
This is the simplest view possible. Go to "/polls/" in your browser, and you
should see your text.
Now add the following view. It's slightly different, because it takes an
argument (which, remember, is passed in from whatever was captured by the
regular expression in the URLconf)::
Now lets add a few more views. These views are slightly different, because
they take an argument (which, remember, is passed in from whatever was
captured by the regular expression in the URLconf)::
def detail(request, poll_id):
return HttpResponse("You're looking at poll %s." % poll_id)
Take a look in your browser, at "/polls/34/". It'll display whatever ID you
provide in the URL.
def results(request, poll_id):
return HttpResponse("You're looking at the results of poll %s." % poll_id)
def vote(request, poll_id):
return HttpResponse("You're voting on poll %s." % poll_id)
Take a look in your browser, at "/polls/34/". It'll run the `detail()` method
and display whatever ID you provide in the URL. Try "/polls/34/results/" and
"/polls/34/vote/" too -- these will display the placeholder results and voting
pages.
Write views that actually do something
======================================
@@ -467,10 +475,10 @@ Copy the file ``mysite/urls.py`` to ``mysite/polls/urls.py``. Then, change
``mysite/urls.py`` to remove the poll-specific URLs and insert an
:func:`~django.conf.urls.defaults.include`::
...
# ...
urlpatterns = patterns('',
(r'^polls/', include('mysite.polls.urls')),
...
# ...
:func:`~django.conf.urls.defaults.include`, simply, references another URLconf.
Note that the regular expression doesn't have a ``$`` (end-of-string match

View File

@@ -21,6 +21,7 @@ tutorial, so that the template contains an HTML ``<form>`` element:
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="/polls/{{ poll.id }}/vote/" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
@@ -46,17 +47,41 @@ A quick rundown:
* ``forloop.counter`` indicates how many times the :ttag:`for` tag has gone
through its loop
* Since we are creating a POST form (which can have the effect of modifying
data), we unfortunately need to worry about Cross Site Request Forgeries.
Thankfully, you don't have to worry too hard, because Django comes with
very easy-to-use system for protecting against it. In short, all POST
forms that are targetted at internal URLs need the ``{% csrf_token %}``
template tag adding.
The ``{% csrf_token %}`` tag requires information from the request object, which
is not normally accessible from within the template context. To fix this, a
small adjustment needs to be made to the ``detail`` view, so that it looks like
the following::
from django.template import RequestContext
# ...
def detail(request, poll_id):
p = get_object_or_404(Poll, pk=poll_id)
return render_to_response('polls/detail.html', {'poll': p},
context_instance=RequestContext(request))
The details of how this works are explained in the documentation for
:ref:`RequestContext <subclassing-context-requestcontext>`.
Now, let's create a Django view that handles the submitted data and does
something with it. Remember, in :ref:`Tutorial 3 <intro-tutorial03>`, we
created a URLconf for the polls application that includes this line::
(r'^(?P<poll_id>\d+)/vote/$', 'vote'),
So let's create a ``vote()`` function in ``mysite/polls/views.py``::
We also created a dummy implementation of the ``vote()`` function. Let's
create a real version. Add the following to ``mysite/polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect
from django.http import HttpResponseRedirect, HttpResponse
from django.core.urlresolvers import reverse
from django.template import RequestContext
from mysite.polls.models import Choice, Poll
# ...
def vote(request, poll_id):
@@ -68,7 +93,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
return render_to_response('polls/detail.html', {
'poll': p,
'error_message': "You didn't select a choice.",
})
}, context_instance=RequestContext(request))
else:
selected_choice.votes += 1
selected_choice.save()

View File

@@ -770,7 +770,7 @@ documented in :ref:`topics-http-urls`::
However, the ``self.my_view`` function registered above suffers from two
problems:
* It will *not* perform and permission checks, so it will be accessible to
* It will *not* perform any permission checks, so it will be accessible to
the general public.
* It will *not* provide any header details to prevent caching. This means if
the page retrieves data from the database, and caching middleware is
@@ -1048,16 +1048,70 @@ automatically::
FriendshipInline,
]
Working with Many-to-Many Models
--------------------------------
.. versionadded:: 1.2
By default, admin widgets for many-to-many relations will be displayed
on whichever model contains the actual reference to the ``ManyToManyField``.
Depending on your ``ModelAdmin`` definition, each many-to-many field in your
model will be represented by a standard HTML ``<select multiple>``, a
horizontal or vertical filter, or a ``raw_id_admin`` widget. However, it is
also possible to to replace these widgets with inlines.
Suppose we have the following models::
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, related_name='groups')
If you want to display many-to-many relations using an inline, you can do
so by defining an ``InlineModelAdmin`` object for the relationship::
class MembershipInline(admin.TabularInline):
model = Group.members.through
class PersonAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
class GroupAdmin(admin.ModelAdmin):
inlines = [
MembershipInline,
]
exclude = ('members',)
There are two features worth noting in this example.
Firstly - the ``MembershipInline`` class references ``Group.members.through``.
The ``through`` attribute is a reference to the model that manages the
many-to-many relation. This model is automatically created by Django when you
define a many-to-many field.
Secondly, the ``GroupAdmin`` must manually exclude the ``members`` field.
Django displays an admin widget for a many-to-many field on the model that
defines the relation (in this case, ``Group``). If you want to use an inline
model to represent the many-to-many relationship, you must tell Django's admin
to *not* display this widget - otherwise you will end up with two widgets on
your admin page for managing the relation.
In all other respects, the ``InlineModelAdmin`` is exactly the same as any
other. You can customize the appearance using any of the normal
``InlineModelAdmin`` properties.
Working with Many-to-Many Intermediary Models
----------------------------------------------
By default, admin widgets for many-to-many relations will be displayed inline
on whichever model contains the actual reference to the ``ManyToManyField``.
However, when you specify an intermediary model using the ``through``
argument to a ``ManyToManyField``, the admin will not display a widget by
default. This is because each instance of that intermediary model requires
more information than could be displayed in a single widget, and the layout
required for multiple widgets will vary depending on the intermediate model.
When you specify an intermediary model using the ``through`` argument to a
``ManyToManyField``, the admin will not display a widget by default. This is
because each instance of that intermediary model requires more information
than could be displayed in a single widget, and the layout required for
multiple widgets will vary depending on the intermediate model.
However, we still want to be able to edit that information inline. Fortunately,
this is easy to do with inline admin models. Suppose we have the following

View File

@@ -216,6 +216,13 @@ should know about:
it with a warning field; if you use the comment form with a custom
template you should be sure to do the same.
The comments app also depends on the more general :ref:`Cross Site Request
Forgery protection < ref-contrib-csrf>` that comes with Django. As described in
the documentation, it is best to use ``CsrfViewMiddleware``. However, if you
are not using that, you will need to use the ``csrf_protect`` decorator on any
views that include the comment form, in order for those views to be able to
output the CSRF token and cookie.
.. _honeypot: http://en.wikipedia.org/wiki/Honeypot_(computing)
More information

View File

@@ -4,121 +4,421 @@
Cross Site Request Forgery protection
=====================================
.. module:: django.contrib.csrf
.. module:: django.middleware.csrf
:synopsis: Protects against Cross Site Request Forgeries
The CsrfMiddleware class provides easy-to-use protection against
The CSRF middleware and template tag provides easy-to-use protection against
`Cross Site Request Forgeries`_. This type of attack occurs when a malicious
Web site creates a link or form button that is intended to perform some action
on your Web site, using the credentials of a logged-in user who is tricked
into clicking on the link in their browser.
Web site contains a link, a form button or some javascript that is intended to
perform some action on your Web site, using the credentials of a logged-in user
who visits the malicious site in their browser. A related type of attack,
'login CSRF', where an attacking site tricks a user's browser into logging into
a site with someone else's credentials, is also covered.
The first defense against CSRF attacks is to ensure that GET requests
are side-effect free. POST requests can then be protected by adding this
middleware into your list of installed middleware.
The first defense against CSRF attacks is to ensure that GET requests are
side-effect free. POST requests can then be protected by following the steps
below.
.. versionadded:: 1.2
The 'contrib' apps, including the admin, use the functionality described
here. Because it is security related, a few things have been added to core
functionality to allow this to happen without any required upgrade steps.
.. _Cross Site Request Forgeries: http://www.squarefree.com/securitytips/web-developers.html#CSRF
How to use it
=============
Add the middleware ``'django.contrib.csrf.middleware.CsrfMiddleware'`` to
your list of middleware classes, :setting:`MIDDLEWARE_CLASSES`. It needs to process
the response after the SessionMiddleware, so must come before it in the
list. It also must process the response before things like compression
happen to the response, so it must come after GZipMiddleware in the
list.
.. versionchanged:: 1.2
The template tag functionality (the recommended way to use this) was added
in version 1.2. The previous method (still available) is described under
`Legacy method`_.
The ``CsrfMiddleware`` class is actually composed of two middleware:
``CsrfViewMiddleware`` which performs the checks on incoming requests,
and ``CsrfResponseMiddleware`` which performs post-processing of the
result. This allows the individual components to be used and/or
replaced instead of using ``CsrfMiddleware``.
To enable CSRF protection for your views, follow these steps:
.. versionchanged:: 1.1
(previous versions of Django did not provide these two components
of ``CsrfMiddleware`` as described above)
1. Add the middleware
``'django.middleware.csrf.CsrfViewMiddleware'`` to your list of
middleware classes, :setting:`MIDDLEWARE_CLASSES`. (It should come
before ``CsrfResponseMiddleware`` if that is being used, and before any
view middleware that assume that CSRF attacks have been dealt with.)
Alternatively, you can use the decorator
``django.views.decorators.csrf.csrf_protect`` on particular views you
want to protect (see below).
2. In any template that uses a POST form, use the ``csrf_token`` tag inside
the ``<form>`` element if the form is for an internal URL, e.g.::
<form action="" method="POST">{% csrf_token %}
This should not be done for POST forms that target external URLs, since
that would cause the CSRF token to be leaked, leading to a vulnerability.
3. In the corresponding view functions, ensure that the
``'django.core.context_processors.csrf'`` context processor is
being used. Usually, this can be done in one of two ways:
1. Use RequestContext, which always uses
``'django.core.context_processors.csrf'`` (no matter what your
TEMPLATE_CONTEXT_PROCESSORS setting). If you are using
generic views or contrib apps, you are covered already, since these
apps use RequestContext throughout.
2. Manually import and use the processor to generate the CSRF token and
add it to the template context. e.g.::
from django.core.context_processors import csrf
from django.shortcuts import render_to_response
def my_view(request):
c = {}
c.update(csrf(request))
# ... view code here
return render_to_response("a_template.html", c)
You may want to write your own ``render_to_response`` wrapper that
takes care of this step for you.
The utility script ``extras/csrf_migration_helper.py`` can help to automate the
finding of code and templates that may need to be upgraded. It contains full
help on how to use it.
The decorator method
--------------------
Rather than adding ``CsrfViewMiddleware`` as a blanket protection, you can use
the ``csrf_protect`` decorator, which has exactly the same functionality, on
particular views that need the protection. It must be used **both** on views
that insert the CSRF token in the output, and on those that accept the POST form
data. (These are often the same view function, but not always). It is used like
this::
from django.views.decorators.csrf import csrf_protect
from django.template import RequestContext
@csrf_protect
def my_view(request):
c = {}
# ...
return render_to_response("a_template.html", c,
context_instance=RequestContext(request))
Use of the decorator is **not recommended** by itself, since if you forget to
use it, you will have a security hole. The 'belt and braces' strategy of using
both is fine, and will incur minimal overhead.
Legacy method
-------------
In Django 1.1, the template tag did not exist. Instead, a post-processing
middleware that re-wrote POST forms to include the CSRF token was used. If you
are upgrading a site from version 1.1 or earlier, please read this section and
the `Upgrading notes`_ below. The post-processing middleware is still available
as ``CsrfResponseMiddleware``, and it can be used by following these steps:
1. Follow step 1 above to install ``CsrfViewMiddleware``.
2. Add ``'django.middleware.csrf.CsrfResponseMiddleware'`` to your
:setting:`MIDDLEWARE_CLASSES` setting.
``CsrfResponseMiddleware`` needs to process the response before things
like compression or setting ofETags happen to the response, so it must
come after ``GZipMiddleware``, ``CommonMiddleware`` and
``ConditionalGetMiddleware`` in the list. It also must come after
``CsrfViewMiddleware``.
Use of the ``CsrfResponseMiddleware`` is not recommended because of the
performance hit it imposes, and because of a potential security problem (see
below). It can be used as an interim measure until applications have been
updated to use the ``{% csrf_token %}`` tag. It is deprecated and will be
removed in Django 1.4.
Django 1.1 and earlier provided a single ``CsrfMiddleware`` class. This is also
still available for backwards compatibility. It combines the functions of the
two middleware.
Note also that previous versions of these classes depended on the sessions
framework, but this dependency has now been removed, with backward compatibility
support so that upgrading will not produce any issues.
Security of legacy method
~~~~~~~~~~~~~~~~~~~~~~~~~
The post-processing ``CsrfResponseMiddleware`` adds the CSRF token to all POST
forms (unless the view has been decorated with ``csrf_response_exempt``). If
the POST form has an external untrusted site as its target, rather than an
internal page, that site will be sent the CSRF token when the form is submitted.
Armed with this leaked information, that site will then be able to successfully
launch a CSRF attack on your site against that user. The
``@csrf_response_exempt`` decorator can be used to fix this, but only if the
page doesn't also contain internal forms that require the token.
Upgrading notes
---------------
When upgrading to version 1.2 or later, you may have applications that rely on
the old post-processing functionality for CSRF protection, or you may not have
enabled any CSRF protection. This section outlines the steps necessary for a
smooth upgrade, without having to fix all the applications to use the new
template tag method immediately.
First of all, the location of the middleware and related functions have
changed. There are backwards compatible stub files so that old imports will
continue to work for now, but they are deprecated and will be removed in Django
1.4. The following changes have been made:
* Middleware have been moved to ``django.middleware.csrf``
* Decorators have been moved to ``django.views.decorators.csrf``
====================================================== ==============================================
Old New
====================================================== ==============================================
django.contrib.csrf.middleware.CsrfMiddleware django.middleware.csrf.CsrfMiddleware
django.contrib.csrf.middleware.CsrfViewMiddleware django.middleware.csrf.CsrfViewMiddleware
django.contrib.csrf.middleware.CsrfResponseMiddleware django.middleware.csrf.CsrfResponseMiddleware
django.contrib.csrf.middleware.csrf_exempt django.views.decorators.csrf_exempt
django.contrib.csrf.middleware.csrf_view_exempt django.views.decorators.csrf_view_exempt
django.contrib.csrf.middleware.csrf_response_exempt django.views.decorators.csrf_response_exempt
====================================================== ==============================================
You should update any imports, and also the paths in your
:setting:`MIDDLEWARE_CLASSES`.
If you have ``CsrfMiddleware`` in your :setting:`MIDDLEWARE_CLASSES`, you will now
have a working installation with CSRF protection. It is recommended at this
point that you replace ``CsrfMiddleware`` with its two components,
``CsrfViewMiddleware`` and ``CsrfResponseMiddleware`` (in that order).
If you do not have any of the middleware in your :setting:`MIDDLEWARE_CLASSES`,
you will have a working installation but without any CSRF protection for your
views (just as you had before). It is strongly recommended to install
``CsrfViewMiddleware`` and ``CsrfResponseMiddleware``, as described above.
Note that contrib apps, such as the admin, have been updated to use the
``csrf_protect`` decorator, so that they are secured even if you do not add the
``CsrfViewMiddleware`` to your settings. However, if you have supplied
customised templates to any of the view functions of contrib apps (whether
explicitly via a keyword argument, or by overriding built-in templates), **you
MUST update them** to include the ``csrf_token`` template tag as described
above, or they will stop working. (If you cannot update these templates for
some reason, you will be forced to use ``CsrfResponseMiddleware`` for these
views to continue working).
Note also, if you are using the comments app, and you are not going to add
``CsrfViewMiddleware`` to your settings (not recommended), you will need to add
the ``csrf_protect`` decorator to any views that include the comment forms and
target the comment views (usually using the :ttag:`comment_form_target` template
tag).
Assuming you have followed the above, all views in your Django site will now be
protected by the ``CsrfViewMiddleware``. Contrib apps meet the requirements
imposed by the ``CsrfViewMiddleware`` using the template tag, and other
applications in your project will meet its requirements by virtue of the
``CsrfResponseMiddleware``.
The next step is to update all your applications to use the template tag, as
described in `How to use it`_, steps 2-3. This can be done as soon as is
practical. Any applications that are updated will now require Django 1.1.2 or
later, since they will use the CSRF template tag which was not available in
earlier versions. (The template tag in 1.1.2 is actually a no-op that exists
solely to ease the transition to 1.2 — it allows apps to be created that have
CSRF protection under 1.2 without requiring users of the apps to upgrade to the
Django 1.2.X series).
The utility script ``extras/csrf_migration_helper.py`` can help to automate the
finding of code and templates that may need to be upgraded. It contains full
help on how to use it.
Finally, once all applications are upgraded, ``CsrfResponseMiddleware`` can be
removed from your settings.
While ``CsrfResponseMiddleware`` is still in use, the ``csrf_response_exempt``
decorator, described in `Exceptions`_, may be useful. The post-processing
middleware imposes a performance hit and a potential vulnerability, and any
views that have been upgraded to use the new template tag method no longer need
it.
Exceptions
----------
.. versionadded:: 1.1
To manually exclude a view function from being handled by the
CsrfMiddleware, you can use the ``csrf_exempt`` decorator, found in
the ``django.contrib.csrf.middleware`` module. For example::
To manually exclude a view function from being handled by either of the two CSRF
middleware, you can use the ``csrf_exempt`` decorator, found in the
``django.views.decorators.csrf`` module. For example::
from django.contrib.csrf.middleware import csrf_exempt
from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
my_view = csrf_exempt(my_view)
Like the middleware itself, the ``csrf_exempt`` decorator is composed
of two parts: a ``csrf_view_exempt`` decorator and a
``csrf_response_exempt`` decorator, found in the same module. These
disable the view protection mechanism (``CsrfViewMiddleware``) and the
response post-processing (``CsrfResponseMiddleware``) respectively.
They can be used individually if required.
Like the middleware, the ``csrf_exempt`` decorator is composed of two parts: a
``csrf_view_exempt`` decorator and a ``csrf_response_exempt`` decorator, found
in the same module. These disable the view protection mechanism
(``CsrfViewMiddleware``) and the response post-processing
(``CsrfResponseMiddleware``) respectively. They can be used individually if
required.
You don't have to worry about doing this for most AJAX views. Any
request sent with "X-Requested-With: XMLHttpRequest" is automatically
exempt. (See the next section.)
You don't have to worry about doing this for most AJAX views. Any request sent
with "X-Requested-With: XMLHttpRequest" is automatically exempt. (See the `How
it works`_ section.)
Subdomains
----------
By default, CSRF cookies are specific to the subdomain they are set for. This
means that a form served from one subdomain (e.g. server1.example.com) will not
be able to have a target on another subdomain (e.g. server2.example.com). This
restriction can be removed by setting :setting:`CSRF_COOKIE_DOMAIN` to be
something like ``".example.com"``.
Please note that, with or without use of this setting, this CSRF protection
mechanism is not safe against cross-subdomain attacks -- see `Limitations`_.
Rejected requests
=================
By default, a '403 Forbidden' response is sent to the user if an incoming
request fails the checks performed by ``CsrfViewMiddleware``. This should
usually only be seen when there is a genuine Cross Site Request Forgery, or
when, due to a programming error, the CSRF token has not been included with a
POST form.
No logging is done, and the error message is not very friendly, so you may want
to provide your own page for handling this condition. To do this, simply set
the :setting:`CSRF_FAILURE_VIEW` setting to a dotted path to your own view
function, which should have the following signature::
def csrf_failure(request, reason="")
where ``reason`` is a short message (intended for developers or logging, not for
end users) indicating the reason the request was rejected.
How it works
============
CsrfMiddleware does two things:
The CSRF protection is based on the following things:
1. It modifies outgoing requests by adding a hidden form field to all
'POST' forms, with the name 'csrfmiddlewaretoken' and a value which is
a hash of the session ID plus a secret. If there is no session ID set,
this modification of the response isn't done, so there is very little
performance penalty for those requests that don't have a session.
(This is done by ``CsrfResponseMiddleware``).
1. A CSRF cookie that is set to a random value (a session independent nonce, as
it is called), which other sites will not have access to.
2. On all incoming POST requests that have the session cookie set, it
checks that the 'csrfmiddlewaretoken' is present and correct. If it
isn't, the user will get a 403 error. (This is done by
``CsrfViewMiddleware``)
This cookie is set by ``CsrfViewMiddleware``. It is meant to be permanent,
but since there is no way to set a cookie that never expires, it is sent with
every response that has called ``django.middleware.csrf.get_token()``
(the function used internally to retrieve the CSRF token).
This ensures that only forms that have originated from your Web site
can be used to POST data back.
2. A hidden form field with the name 'csrfmiddlewaretoken' present in all
outgoing POST forms. The value of this field is the value of the CSRF
cookie.
This part is done by the template tag (and with the legacy method, it is done
by ``CsrfResponseMiddleware``).
3. For all incoming POST requests, a CSRF cookie must be present, and the
'csrfmiddlewaretoken' field must be present and correct. If it isn't, the
user will get a 403 error.
This check is done by ``CsrfViewMiddleware``.
4. In addition, for HTTPS requests, strict referer checking is done by
``CsrfViewMiddleware``. This is necessary to address a Man-In-The-Middle
attack that is possible under HTTPS when using a session independent nonce,
due to the fact that HTTP 'Set-Cookie' headers are (unfortunately) accepted
by clients that are talking to a site under HTTPS. (Referer checking is not
done for HTTP requests because the presence of the Referer header is not
reliable enough under HTTP.)
This ensures that only forms that have originated from your Web site can be used
to POST data back.
It deliberately only targets HTTP POST requests (and the corresponding POST
forms). GET requests ought never to have any potentially dangerous side
effects (see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a
CSRF attack with a GET request ought to be harmless.
forms). GET requests ought never to have any potentially dangerous side effects
(see `9.1.1 Safe Methods, HTTP 1.1, RFC 2616`_), and so a CSRF attack with a GET
request ought to be harmless.
POST requests that are not accompanied by a session cookie are not protected,
but they do not need to be protected, since the 'attacking' Web site
could make these kind of requests anyway.
``CsrfResponseMiddleware`` checks the Content-Type before modifying the
response, and only pages that are served as 'text/html' or
'application/xml+xhtml' are modified.
The Content-Type is checked before modifying the response, and only
pages that are served as 'text/html' or 'application/xml+xhtml'
are modified.
AJAX
----
The middleware tries to be smart about requests that come in via AJAX. Many
JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP header;
these requests are detected and automatically *not* handled by this middleware.
We can do this safely because, in the context of a browser, the header can only
be added by using ``XMLHttpRequest``, and browsers already implement a
same-domain policy for ``XMLHttpRequest``. (Note that this is not secure if you
don't trust content within the same domain or subdomains.)
The middleware tries to be smart about requests that come in via AJAX. Most
modern JavaScript toolkits send an "X-Requested-With: XMLHttpRequest" HTTP
header; these requests are detected and automatically *not* handled by this
middleware. We can do this safely because, in the context of a browser, the
header can only be added by using ``XMLHttpRequest``, and browsers already
implement a same-domain policy for ``XMLHttpRequest``.
For the more recent browsers that relax this same-domain policy, custom headers
like "X-Requested-With" are only allowed after the browser has done a
'preflight' check to the server to see if the cross-domain request is allowed,
using a strictly 'opt in' mechanism, so the exception for AJAX is still safe—if
the developer has specifically opted in to allowing cross-site AJAX POST
requests on a specific URL, they obviously don't want the middleware to disallow
exactly that.
.. _9.1.1 Safe Methods, HTTP 1.1, RFC 2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
Caching
=======
If the ``csrf_token`` template tag is used by a template (or the ``get_token``
function is called some other way), ``CsrfViewMiddleware`` will add a cookie and
a ``Vary: Cookie`` header to the response. Similarly,
``CsrfResponseMiddleware`` will send the ``Vary: Cookie`` header if it inserted
a token. This means that these middleware will play well with the cache
middleware if it is used as instructed (``UpdateCacheMiddleware`` goes before
all other middleware).
However, if you use cache decorators on individual views, the CSRF middleware
will not yet have been able to set the Vary header. In this case, on any views
that will require a CSRF token to be inserted you should use the
:func:`django.views.decorators.vary.vary_on_cookie` decorator first::
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie
@cache_page(60 * 15)
@vary_on_cookie
def my_view(request):
# ...
Testing
=======
The ``CsrfViewMiddleware`` will usually be a big hindrance to testing view
functions, due to the need for the CSRF token which must be sent with every POST
request. For this reason, Django's HTTP client for tests has been modified to
set a flag on requests which relaxes the middleware and the ``csrf_protect``
decorator so that they no longer rejects requests. In every other respect
(e.g. sending cookies etc.), they behave the same.
Limitations
===========
CsrfMiddleware requires Django's session framework to work. If you have
a custom authentication system that manually sets cookies and the like,
it won't help you.
Subdomains within a site will be able to set cookies on the client for the whole
domain. By setting the cookie and using a corresponding token, subdomains will
be able to circumvent the CSRF protection. The only way to avoid this is to
ensure that subdomains are controlled by trusted users (or, are at least unable
to set cookies). Note that even without CSRF, there are other vulnerabilities,
such as session fixation, that make giving subdomains to untrusted parties a bad
idea, and these vulnerabilities cannot easily be fixed with current browsers.
If your app creates HTML pages and forms in some unusual way, (e.g.
it sends fragments of HTML in JavaScript document.write statements)
you might bypass the filter that adds the hidden field to the form,
in which case form submission will always fail. It may still be possible
to use the middleware, provided you can find some way to get the
CSRF token and ensure that is included when your form is submitted.
If you are using ``CsrfResponseMiddleware`` and your app creates HTML pages and
forms in some unusual way, (e.g. it sends fragments of HTML in JavaScript
document.write statements) you might bypass the filter that adds the hidden
field to the form, in which case form submission will always fail. You should
use the template tag or :meth:`django.middleware.csrf.get_token` to get
the CSRF token and ensure it is included when your form is submitted.
Contrib and reusable apps
=========================
Because it is possible for the developer to turn off the ``CsrfViewMiddleware``,
all relevant views in contrib apps use the ``csrf_protect`` decorator to ensure
the security of these applications against CSRF. It is recommended that the
developers of other reusable apps that want the same guarantees also use the
``csrf_protect`` decorator on their views.

View File

@@ -177,7 +177,7 @@ Here's a full example template:
{% block content %}
<p>Step {{ step }} of {{ step_count }}</p>
<form action="." method="post">
<form action="." method="post">{% csrf_token %}
<table>
{{ form }}
</table>

View File

@@ -78,11 +78,9 @@ Examples of output::
Displaying debug output
-----------------------
.. django-admin-option:: --verbosity <amount>
Use ``--verbosity`` to specify the amount of notification and debug information
Use :djadminopt:`--verbosity` to specify the amount of notification and debug information
that ``django-admin.py`` should print to the console. For more details, see the
documentation for the :ref:`default options for django-admin.py <django-admin-verbosity>`.
documentation for the :djadminopt:`--verbosity` option.
Available subcommands
=====================
@@ -90,6 +88,8 @@ Available subcommands
cleanup
-------
.. django-admin:: cleanup
.. versionadded:: 1.0
Can be run as a cronjob or directly to clean out old data from the database
@@ -98,17 +98,16 @@ Can be run as a cronjob or directly to clean out old data from the database
compilemessages
---------------
.. django-admin:: compilemessages
.. versionchanged:: 1.0
Before 1.0 this was the "bin/compile-messages.py" command.
Compiles .po files created with ``makemessages`` to .mo files for use with
the builtin gettext support. See :ref:`topics-i18n`.
--locale
~~~~~~~~
Use the ``--locale`` or ``-l`` option to specify the locale to process.
If not provided all locales are processed.
Use the :djadminopt:`--locale`` option to specify the locale to process.
If not provided, all locales are processed.
Example usage::
@@ -117,7 +116,7 @@ Example usage::
createcachetable
----------------
.. django-admin:: createcachetable <tablename>
.. django-admin:: createcachetable
Creates a cache table named ``tablename`` for use with the database cache
backend. See :ref:`topics-cache` for more information.
@@ -196,10 +195,10 @@ example, the default settings don't define ``ROOT_URLCONF``, so
Note that Django's default settings live in ``django/conf/global_settings.py``,
if you're ever curious to see the full list of defaults.
dumpdata
--------
dumpdata <appname appname appname.Model ...>
--------------------------------------------
.. django-admin:: dumpdata <appname appname appname.Model ...>
.. django-admin:: dumpdata
Outputs to standard output all data in the database associated with the named
application(s).
@@ -228,18 +227,17 @@ directives::
django-admin.py dumpdata --exclude=auth --exclude=contenttypes
.. django-admin-option:: --format <fmt>
By default, ``dumpdata`` will format its output in JSON, but you can use the
``--format`` option to specify another format. Currently supported formats
are listed in :ref:`serialization-formats`.
By default, ``dumpdata`` will format its output in JSON, but you can use the
``--format`` option to specify another format. Currently supported formats
are listed in :ref:`serialization-formats`.
.. django-admin-option:: --indent <num>
By default, ``dumpdata`` will output all data on a single line. This isn't
easy for humans to read, so you can use the ``--indent`` option to
pretty-print the output with a number of indentation spaces.
By default, ``dumpdata`` will output all data on a single line. This isn't
easy for humans to read, so you can use the ``--indent`` option to
pretty-print the output with a number of indentation spaces.
.. versionadded:: 1.1
@@ -252,18 +250,15 @@ model names.
flush
-----
.. django-admin: flush
.. django-admin:: flush
Returns the database to the state it was in immediately after syncdb was
executed. This means that all data will be removed from the database, any
post-synchronization handlers will be re-executed, and the ``initial_data``
fixture will be re-installed.
.. django-admin-option:: --noinput
Use the ``--noinput`` option to suppress all user prompting, such as "Are
you sure?" confirmation messages. This is useful if ``django-admin.py`` is
being executed as an unattended, automated script.
The :djadminopt:`--noinput` option may be provided to suppress all user
prompts.
--database
~~~~~~~~~~
@@ -274,6 +269,8 @@ The alias for the database to flush. By default flushes all databases.
inspectdb
---------
.. django-admin:: inspectdb
Introspects the database tables in the database pointed-to by the
``DATABASE_NAME`` setting and outputs a Django model module (a ``models.py``
file) to standard output.
@@ -322,6 +319,8 @@ alias.
loaddata <fixture fixture ...>
------------------------------
.. django-admin:: loaddata
Searches for and loads the contents of the named fixture into the database.
What's a "fixture"?
@@ -408,6 +407,8 @@ installation will be aborted, and any data installed in the call to
makemessages
------------
.. django-admin:: makemessages
.. versionchanged:: 1.0
Before 1.0 this was the ``bin/make-messages.py`` command.
@@ -418,8 +419,7 @@ directory. After making changes to the messages files you need to compile them
with ``compilemessages`` for use with the builtin gettext support. See the
:ref:`i18n documentation <how-to-create-language-files>` for details.
--all
~~~~~
.. django-admin-option:: --all
Use the ``--all`` or ``-a`` option to update the message files for all
available languages.
@@ -428,8 +428,7 @@ Example usage::
django-admin.py makemessages --all
--extension
~~~~~~~~~~~
.. django-admin-option:: --extension
Use the ``--extension`` or ``-e`` option to specify a list of file extensions
to examine (default: ".html").
@@ -442,17 +441,13 @@ Separate multiple extensions with commas or use -e or --extension multiple times
django-admin.py makemessages --locale=de --extension=html,txt --extension xml
--locale
~~~~~~~~
Use the ``--locale`` or ``-l`` option to specify the locale to process.
Use the :djadminopt:`--locale` option to specify the locale to process.
Example usage::
django-admin.py makemessages --locale=br_PT
--domain
~~~~~~~~
.. django-admin-option:: --domain
Use the ``--domain`` or ``-d`` option to change the domain of the messages files.
Currently supported:
@@ -460,19 +455,15 @@ Currently supported:
* ``django`` for all ``*.py`` and ``*.html`` files (default)
* ``djangojs`` for ``*.js`` files
.. _django-admin-reset:
reset <appname appname ...>
---------------------------
.. django-admin:: reset
Executes the equivalent of ``sqlreset`` for the given app name(s).
--noinput
~~~~~~~~~
Use the ``--noinput`` option to suppress all user prompting, such as
"Are you sure?" confirmation messages. This is useful if ``django-admin.py``
is being executed as an unattended, automated script.
The :djadminopt:`--noinput` option may be provided to suppress all user
prompts.
--database
~~~~~~~~~~
@@ -482,6 +473,8 @@ The alias for the database to reset. By default resets all databases.
runfcgi [options]
-----------------
.. django-admin:: runfcgi
Starts a set of FastCGI processes suitable for use with any Web server that
supports the FastCGI protocol. See the :ref:`FastCGI deployment documentation
<howto-deployment-fastcgi>` for details. Requires the Python FastCGI module from
@@ -489,10 +482,10 @@ supports the FastCGI protocol. See the :ref:`FastCGI deployment documentation
.. _flup: http://www.saddi.com/software/flup/
runserver
---------
runserver [port or ipaddr:port]
-------------------------------
.. django-admin:: runserver [port or ipaddr:port]
.. django-admin:: runserver
Starts a lightweight development Web server on the local machine. By default,
the server runs on port 8000 on the IP address 127.0.0.1. You can pass in an
@@ -575,6 +568,8 @@ you want to configure Django to serve static media, read :ref:`howto-static-file
shell
-----
.. django-admin:: shell
Starts the Python interactive interpreter.
Django will use IPython_, if it's installed. If you have IPython installed and
@@ -588,6 +583,8 @@ option, like so::
sql <appname appname ...>
-------------------------
.. django-admin:: sql
Prints the CREATE TABLE SQL statements for the given app name(s).
--database
@@ -600,6 +597,8 @@ The alias for the database to print the SQL for. By default uses the
sqlall <appname appname ...>
----------------------------
.. django-admin:: sqlall
Prints the CREATE TABLE and initial-data SQL statements for the given app name(s).
Refer to the description of ``sqlcustom`` for an explanation of how to
@@ -614,6 +613,8 @@ The alias for the database to print the SQL for. By default uses the
sqlclear <appname appname ...>
------------------------------
.. django-admin:: sqlclear
Prints the DROP TABLE SQL statements for the given app name(s).
--database
@@ -625,6 +626,8 @@ The alias for the database to print the SQL for. By default uses the
sqlcustom <appname appname ...>
-------------------------------
.. django-admin:: sqlcustom
Prints the custom SQL statements for the given app name(s).
For each model in each specified app, this command looks for the file
@@ -650,7 +653,10 @@ The alias for the database to print the SQL for. By default uses the
sqlflush
--------
Prints the SQL statements that would be executed for the `flush`_ command.
.. django-admin:: sqlflush
Prints the SQL statements that would be executed for the :djadmin:`flush`
command.
--database
~~~~~~~~~~
@@ -661,6 +667,8 @@ The alias for the database to print the SQL for. By default uses the
sqlindexes <appname appname ...>
--------------------------------
.. django-admin:: sqlindexes
Prints the CREATE INDEX SQL statements for the given app name(s).
--database
@@ -672,6 +680,8 @@ The alias for the database to print the SQL for. By default uses the
sqlreset <appname appname ...>
------------------------------
.. django-admin:: sqlreset
Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s).
--database
@@ -683,6 +693,8 @@ The alias for the database to print the SQL for. By default uses the
sqlsequencereset <appname appname ...>
--------------------------------------
.. django-admin:: sqlsequencereset
Prints the SQL statements for resetting sequences for the given app name(s).
Sequences are indexes used by some database engines to track the next available
@@ -700,12 +712,16 @@ The alias for the database to print the SQL for. By default uses the
startapp <appname>
------------------
.. django-admin:: startapp
Creates a Django app directory structure for the given app name in the current
directory.
startproject <projectname>
--------------------------
.. django-admin:: startproject
Creates a Django project directory structure for the given project name in the
current directory.
@@ -715,11 +731,11 @@ This command is disabled when the ``--settings`` option to
situations, either omit the ``--settings`` option or unset
``DJANGO_SETTINGS_MODULE``.
.. _django-admin-syncdb:
syncdb
------
.. django-admin:: syncdb
Creates the database tables for all apps in ``INSTALLED_APPS`` whose tables
have not already been created.
@@ -749,35 +765,22 @@ with an appropriate extension (e.g. ``json`` or ``xml``). See the
documentation for ``loaddata`` for details on the specification of fixture
data files.
--database
~~~~~~~~~~
The :djadminopt:`--noinput` option may be provided to suppress all user
prompts.
The alias for the database install the tables for. By default uses the
``'default'`` alias.
test <app or test identifier>
-----------------------------
--noinput
~~~~~~~~~
Use the ``--noinput`` option to suppress all user prompting, such as
"Are you sure?" confirmation messages. This is useful if ``django-admin.py``
is being executed as an unattended, automated script.
test
----
.. django-admin:: test
Runs tests for all installed models. See :ref:`topics-testing` for more
information.
--noinput
~~~~~~~~~
Use the ``--noinput`` option to suppress all user prompting, such as
"Are you sure?" confirmation messages. This is useful if ``django-admin.py``
is being executed as an unattended, automated script.
testserver <fixture fixture ...>
--------------------------------
.. django-admin:: testserver
.. versionadded:: 1.0
Runs a Django development server (as in ``runserver``) using data from the
@@ -813,8 +816,7 @@ Note that this server does *not* automatically detect changes to your Python
source code (as ``runserver`` does). It does, however, detect changes to
templates.
--addrport [port number or ipaddr:port]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. django-admin-option:: --addrport [port number or ipaddr:port]
Use ``--addrport`` to specify a different port, or IP address and port, from
the default of 127.0.0.1:8000. This value follows exactly the same format and
@@ -838,6 +840,8 @@ To run on 1.2.3.4:7000 with a ``test`` fixture::
validate
--------
.. django-admin:: validate
Validates all installed models (according to the ``INSTALLED_APPS`` setting)
and prints validation errors to standard output.
@@ -847,8 +851,7 @@ Default options
Although some subcommands may allow their own custom options, every subcommand
allows for the following options:
--pythonpath
------------
.. django-admin-option:: --pythonpath
Example usage::
@@ -863,8 +866,7 @@ setting the Python path for you.
.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
--settings
----------
.. django-admin-option:: --settings
Example usage::
@@ -878,8 +880,7 @@ variable.
Note that this option is unnecessary in ``manage.py``, because it uses
``settings.py`` from the current project by default.
--traceback
-----------
.. django-admin-option:: --traceback
Example usage::
@@ -889,10 +890,7 @@ By default, ``django-admin.py`` will show a simple error message whenever an
error occurs. If you specify ``--traceback``, ``django-admin.py`` will
output a full stack trace whenever an exception is raised.
.. _django-admin-verbosity:
--verbosity
-----------
.. django-admin-option:: --verbosity
Example usage::
@@ -905,6 +903,23 @@ that ``django-admin.py`` should print to the console.
* ``1`` means normal output (default).
* ``2`` means verbose output.
Common options
==============
The following options are not available on every commands, but they are
common to a number of commands.
.. django-admin-option:: --locale
Use the ``--locale`` or ``-l`` option to specify the locale to process.
If not provided all locales are processed.
.. django-admin-option:: --noinput
Use the ``--noinput`` option to suppress all user prompting, such as "Are
you sure?" confirmation messages. This is useful if ``django-admin.py`` is
being executed as an unattended, automated script.
Extra niceties
==============
@@ -930,5 +945,4 @@ distribution. It enables tab-completion of ``django-admin.py`` and
with ``sql``.
See :ref:`howto-custom-management-commands` for how to add customized actions.

View File

@@ -165,11 +165,11 @@ every incoming ``HttpRequest`` object. See :ref:`Authentication in Web requests
CSRF protection middleware
--------------------------
.. module:: django.contrib.csrf.middleware
.. module:: django.middleware.csrf
:synopsis: Middleware adding protection against Cross Site Request
Forgeries.
.. class:: django.contrib.csrf.middleware.CsrfMiddleware
.. class:: django.middleware.csrf.CsrfMiddleware
.. versionadded:: 1.0

View File

@@ -94,9 +94,8 @@ See the docs for :meth:`~django.db.models.QuerySet.latest` for more.
.. versionadded:: 1.1
Defaults to ``True``, meaning Django will create the appropriate database
tables in :ref:`django-admin-syncdb` and remove them as part of a :ref:`reset
<django-admin-reset>` management command. That is, Django *manages* the
database tables' lifecycles.
tables in :djadmin:`syncdb` and remove them as part of a :djadmin:`reset`
management command. That is, Django *manages* the database tables' lifecycles.
If ``False``, no database table creation or deletion operations will be
performed for this model. This is useful if the model represents an existing

View File

@@ -1132,6 +1132,17 @@ Aggregation <topics-db-aggregation>`.
.. _field-lookups:
``exists()``
~~~~~~~~~~~~
.. versionadded:: 1.2
Returns ``True`` if the :class:`QuerySet` contains any results, and ``False``
if not. This tries to perform the query in the simplest and fastest way
possible, but it *does* execute nearly the same query. This means that calling
:meth:`QuerySet.exists()` is faster that ``bool(some_query_set)``, but not by
a large degree.
Field lookups
-------------

View File

@@ -146,6 +146,52 @@ The default number of seconds to cache a page when the caching middleware or
.. setting:: DATABASES
.. setting:: CSRF_COOKIE_NAME
CSRF_COOKIE_NAME
----------------
.. versionadded:: 1.2
Default: ``'csrftoken'``
The name of the cookie to use for the CSRF authentication token. This can be whatever you
want. See :ref:`ref-contrib-csrf`.
.. setting:: CSRF_COOKIE_DOMAIN
CSRF_COOKIE_DOMAIN
------------------
.. versionadded:: 1.2
Default: ``None``
The domain to be used when setting the CSRF cookie. This can be useful for
allowing cross-subdomain requests to be exluded from the normal cross site
request forgery protection. It should be set to a string such as
``".lawrence.com"`` to allow a POST request from a form on one subdomain to be
accepted by accepted by a view served from another subdomain.
.. setting:: CSRF_FAILURE_VIEW
CSRF_FAILURE_VIEW
-----------------
.. versionadded:: 1.2
Default: ``'django.views.csrf.csrf_failure'``
A dotted path to the view function to be used when an incoming request
is rejected by the CSRF protection. The function should have this signature::
def csrf_failure(request, reason="")
where ``reason`` is a short message (intended for developers or logging, not for
end users) indicating the reason the request was rejected. See
:ref:`ref-contrib-csrf`.
DATABASES
---------
@@ -162,6 +208,7 @@ are used:
settings, the usage of those has been deprecated but will be supported
until Django 1.4.
.. setting:: DATABASE_ENGINE
DATABASE_ENGINE
~~~~~~~~~~~~~~~
@@ -431,6 +478,29 @@ are not allowed to visit any page, systemwide. Use this for bad robots/crawlers.
This is only used if ``CommonMiddleware`` is installed (see
:ref:`topics-http-middleware`).
.. setting:: EMAIL_BACKEND
EMAIL_BACKEND
-------------
.. versionadded:: 1.2
Default: ``'django.core.mail.backends.smtp'``
The backend to use for sending emails. For the list of available backends see
:ref:`topics-email`.
.. setting:: EMAIL_FILE_PATH
EMAIL_FILE_PATH
---------------
.. versionadded:: 1.2
Default: Not defined
The directory used by the ``file`` email backend to store output files.
.. setting:: EMAIL_HOST
EMAIL_HOST
@@ -803,6 +873,7 @@ Default::
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',)
A tuple of middleware classes to use. See :ref:`topics-http-middleware`.

View File

@@ -313,6 +313,13 @@ and return a dictionary of items to be merged into the context. By default,
"django.core.context_processors.i18n",
"django.core.context_processors.media")
.. versionadded:: 1.2
In addition to these, ``RequestContext`` always uses
``'django.core.context_processors.csrf'``. This is a security
related context processor required by the admin and other contrib apps, and,
in case of accidental misconfiguration, it is deliberately hardcoded in and
cannot be turned off by the :setting:`TEMPLATE_CONTEXT_PROCESSORS` setting.
Each processor is applied in order. That means, if one processor adds a
variable to the context and a second processor adds a variable with the same
name, the second will override the first. The default processors are explained
@@ -404,6 +411,14 @@ If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every
``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
value of the :setting:`MEDIA_URL` setting.
django.core.context_processors.csrf
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.2
This processor adds a token that is needed by the ``csrf_token`` template tag
for protection against :ref:`Cross Site Request Forgeries <ref-contrib-csrf>`.
django.core.context_processors.request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -53,6 +53,16 @@ Ignore everything between ``{% comment %}`` and ``{% endcomment %}``
.. templatetag:: cycle
csrf_token
~~~~~~~~~~
.. versionadded:: 1.1.2
In the Django 1.1.X series, this is a no-op tag that returns an empty string for
future compatibility purposes. In Django 1.2 and later, it is used for CSRF
protection, as described in the documentation for :ref:`Cross Site Request
Forgeries <ref-contrib-csrf>`.
cycle
~~~~~

View File

@@ -14,8 +14,10 @@ fixes, and an easy upgrade path from Django 1.0.
.. _new features: `What's new in Django 1.1`_
Backwards-incompatible changes
==============================
.. _backwards-incompatible-changes-1.1:
Backwards-incompatible changes in 1.1
=====================================
Django has a policy of :ref:`API stability <misc-api-stability>`. This means
that, in general, code you develop against Django 1.0 should continue to work
@@ -150,6 +152,8 @@ Django 1.1 adds a ``permanent`` argument to the
backwards-incompatible if you were using the ``redirect_to`` view with a
format-string key called 'permanent', which is highly unlikely.
.. _deprecated-features-1.1:
Features deprecated in 1.1
==========================
@@ -289,6 +293,7 @@ test client:
* The test :class:`Client` now can automatically follow redirects with the
``follow`` argument to :meth:`Client.get` and :meth:`Client.post`. This
makes testing views that issue redirects simpler.
* It's now easier to get at the template context in the response returned
the test client: you'll simply access the context as
``request.context[key]``. The old way, which treats ``request.context`` as

70
docs/releases/1.2.txt Normal file
View File

@@ -0,0 +1,70 @@
.. _releases-1.2:
============================================
Django 1.2 release notes — UNDER DEVELOPMENT
============================================
This page documents release notes for the as-yet-unreleased Django 1.2. As such
it is tentative and subject to change. It provides up-to-date information for
those who are following trunk.
.. _backwards-incompatible-changes-1.2:
Backwards-incompatible changes in 1.2
=====================================
CSRF Protection
---------------
There have been large changes to the way that CSRF protection works, detailed in
:ref:`the CSRF documentaton <ref-contrib-csrf>`. The following are the major
changes that developers must be aware of:
* ``CsrfResponseMiddleware`` and ``CsrfMiddleware`` have been deprecated, and
will be removed completely in Django 1.4, in favour of a template tag that
should be inserted into forms.
* All contrib apps use a ``csrf_protect`` decorator to protect the view. This
requires the use of the csrf_token template tag in the template, so if you
have used custom templates for contrib views, you MUST READ THE UPGRADE
INSTRUCTIONS to fix those templates.
* ``CsrfViewMiddleware`` is included in :setting:`MIDDLEWARE_CLASSES` by
default. This turns on CSRF protection by default, so that views that accept
POST requests need to be written to work with the middleware. Instructions
on how to do this are found in the CSRF docs.
* All of the CSRF has moved from contrib to core (with backwards compatible
imports in the old locations, which are deprecated).
LazyObject
----------
``LazyObject`` is an undocumented utility class used for lazily wrapping other
objects of unknown type. In Django 1.1 and earlier, it handled introspection in
a non-standard way, depending on wrapped objects implementing a public method
``get_all_members()``. Since this could easily lead to name clashes, it has been
changed to use the standard method, involving ``__members__`` and ``__dir__()``.
If you used ``LazyObject`` in your own code, and implemented the
``get_all_members()`` method for wrapped objects, you need to make the following
changes:
* If your class does not have special requirements for introspection (i.e. you
have not implemented ``__getattr__()`` or other methods that allow for
attributes not discoverable by normal mechanisms), you can simply remove the
``get_all_members()`` method. The default implementation on ``LazyObject``
will do the right thing.
* If you have more complex requirements for introspection, first rename the
``get_all_members()`` method to ``__dir__()``. This is the standard method,
from Python 2.6 onwards, for supporting introspection. If you are require
support for Python < 2.6, add the following code to the class::
__members__ = property(lambda self: self.__dir__())
.. _deprecated-features-1.2:
Features deprecated in 1.2
==========================
None.

View File

@@ -24,11 +24,20 @@ changes made in that version.
1.1-rc-1
1.1
.. seealso::
Upgrading
=========
The list of `backwards-incompatible changes`_ made in the current
development "trunk". If you're running versions of Django newer than an
official release, you should keep track of new pieces pointed there. It's
also fun reading if you're looking forward to new versions of Django.
For those upgrading to a new version of Django, you will need to check all the
backwards-incompatible changes and deprecated features for each 'final' release
from the one after your old version up to and including your new version. The
relevant sections of the release notes are linked below below for your
convenience.
.. _backwards-incompatible changes: http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges
For those following trunk, the tentative release notes for the next version to
be released are also included at the bottom. This is kept up to date with new
features and changes that you need to be aware of.
* :ref:`backwards-incompatible-changes-1.1`
* :ref:`deprecated-features-1.1`
* :ref:`backwards-incompatible-changes-1.2`
* :ref:`deprecated-features-1.2`

View File

@@ -262,8 +262,8 @@ Manager functions
Creates, saves and returns a :class:`~django.contrib.auth.models.User`.
The :attr:`~django.contrib.auth.models.User.username`,
:attr:`~django.contrib.auth.models.User.email` and
:attr:`~django.contrib.auth.models.User.password` are set as given, and
the :class:`~django.contrib.auth.models.User` gets ``is_active=True``.
:attr:`~django.contrib.auth.models.User.password` are set as given, and the
:class:`~django.contrib.auth.models.User` gets ``is_active=True``.
If no password is provided,
:meth:`~django.contrib.auth.models.User.set_unusable_password()` will
@@ -705,7 +705,7 @@ the following line to your URLconf::
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
.. function:: views.login(request, [template_name, redirect_field_name])
.. function:: views.login(request, [template_name, redirect_field_name, authentication_form])
Here's what ``django.contrib.auth.views.login`` does:
@@ -767,7 +767,7 @@ the following line to your URLconf::
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url django.contrib.auth.views.login %}">
<form method="post" action="{% url django.contrib.auth.views.login %}">{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
@@ -785,6 +785,15 @@ the following line to your URLconf::
{% endblock %}
.. versionadded:: 1.2
If you are using alternate authentication (see
:ref:`authentication-backends`) you can pass a custom authentication form
to the login view via the ``authentication_form`` parameter. This form must
accept a ``request`` keyword argument in its ``__init__`` method, and
provide a ``get_user`` argument which returns the authenticated user object
(this method is only ever called after successful form validation).
.. _forms documentation: ../forms/
.. _site framework docs: ../sites/
@@ -824,7 +833,7 @@ includes a few other useful built-in views located in
* ``login_url``: The URL of the login page to redirect to. This will
default to :setting:`settings.LOGIN_URL <LOGIN_URL>` if not supplied.
.. function:: views.password_change(request[, template_name, post_change_redirect])
.. function:: views.password_change(request[, template_name, post_change_redirect, password_change_form])
Allows a user to change their password.
@@ -837,6 +846,13 @@ includes a few other useful built-in views located in
* ``post_change_redirect``: The URL to redirect to after a successful
password change.
* .. versionadded:: 1.2
``password_change_form``: A custom "change password" form which must
accept a ``user`` keyword argument. The form is responsible for
actually changing the user's password.
**Template context:**
* ``form``: The password change form.
@@ -1030,15 +1046,7 @@ checks to make sure the user is logged in and has the permission
optional ``login_url`` argument, which lets you specify the URL for your
login page (:setting:`settings.LOGIN_URL <LOGIN_URL>` by default).
Example in Python 2.3 syntax::
from django.contrib.auth.decorators import user_passes_test
def my_view(request):
# ...
my_view = user_passes_test(lambda u: u.has_perm('polls.can_vote'), login_url='/login/')(my_view)
Example in Python 2.4 syntax::
For example::
from django.contrib.auth.decorators import user_passes_test

View File

@@ -179,9 +179,9 @@ Local-memory caching
If you want the speed advantages of in-memory caching but don't have the
capability of running Memcached, consider the local-memory cache backend. This
cache is multi-process and thread-safe. To use it, set ``CACHE_BACKEND`` to
``"locmem:///"``. For example::
``"locmem://"``. For example::
CACHE_BACKEND = 'locmem:///'
CACHE_BACKEND = 'locmem://'
Note that each process will have its own private cache instance, which means no
cross-process caching is possible. This obviously also means the local memory
@@ -199,7 +199,7 @@ various places but a development/test environment where you don't want to cache
and don't want to have to change your code to special-case the latter. To
activate dummy caching, set ``CACHE_BACKEND`` like so::
CACHE_BACKEND = 'dummy:///'
CACHE_BACKEND = 'dummy://'
Using a custom cache backend
----------------------------
@@ -249,7 +249,7 @@ In this example, ``timeout`` is set to ``60``::
In this example, ``timeout`` is ``30`` and ``max_entries`` is ``400``::
CACHE_BACKEND = "locmem:///?timeout=30&max_entries=400"
CACHE_BACKEND = "locmem://?timeout=30&max_entries=400"
Invalid arguments are silently ignored, as are invalid values of known
arguments.
@@ -451,11 +451,11 @@ The low-level cache API
Sometimes, caching an entire rendered page doesn't gain you very much and is,
in fact, inconvenient overkill.
Perhaps, for instance, your site includes a view whose results depend on
Perhaps, for instance, your site includes a view whose results depend on
several expensive queries, the results of which change at different intervals.
In this case, it would not be ideal to use the full-page caching that the
per-site or per-view cache strategies offer, because you wouldn't want to
cache the entire result (since some of the data changes often), but you'd still
In this case, it would not be ideal to use the full-page caching that the
per-site or per-view cache strategies offer, because you wouldn't want to
cache the entire result (since some of the data changes often), but you'd still
want to cache the results that rarely change.
For cases like this, Django exposes a simple, low-level cache API. You can use
@@ -616,12 +616,6 @@ like so::
from django.views.decorators.vary import vary_on_headers
# Python 2.3 syntax.
def my_view(request):
# ...
my_view = vary_on_headers(my_view, 'User-Agent')
# Python 2.4+ decorator syntax.
@vary_on_headers('User-Agent')
def my_view(request):
# ...
@@ -763,10 +757,10 @@ Django comes with a few other pieces of middleware that can help optimize your
apps' performance:
* ``django.middleware.http.ConditionalGetMiddleware`` adds support for
modern browsers to conditionally GET responses based on the ``ETag``
modern browsers to conditionally GET responses based on the ``ETag``
and ``Last-Modified`` headers.
* ``django.middleware.gzip.GZipMiddleware`` compresses responses for all
* ``django.middleware.gzip.GZipMiddleware`` compresses responses for all
moderns browsers, saving bandwidth and transfer time.
Order of MIDDLEWARE_CLASSES

View File

@@ -95,13 +95,6 @@ for your front page view::
def front_page(request, blog_id):
...
Of course, if you're using Python 2.3 or prefer not to use the decorator
syntax, you can write the same code as follows, there is no difference::
def front_page(request, blog_id):
...
front_page = condition(last_modified_func=latest_entry)(front_page)
Shortcuts for only computing one value
======================================

View File

@@ -7,11 +7,13 @@ Sending e-mail
.. module:: django.core.mail
:synopsis: Helpers to easily send e-mail.
Although Python makes sending e-mail relatively easy via the `smtplib library`_,
Django provides a couple of light wrappers over it, to make sending e-mail
extra quick.
Although Python makes sending e-mail relatively easy via the `smtplib
library`_, Django provides a couple of light wrappers over it. These wrappers
are provided to make sending e-mail extra quick, to make it easy to test
email sending during development, and to provide support for platforms that
can't use SMTP.
The code lives in a single module: ``django.core.mail``.
The code lives in the ``django.core.mail`` module.
.. _smtplib library: http://docs.python.org/library/smtplib.html
@@ -25,11 +27,11 @@ In two lines::
send_mail('Subject here', 'Here is the message.', 'from@example.com',
['to@example.com'], fail_silently=False)
Mail is sent using the SMTP host and port specified in the :setting:`EMAIL_HOST`
and :setting:`EMAIL_PORT` settings. The :setting:`EMAIL_HOST_USER` and
:setting:`EMAIL_HOST_PASSWORD` settings, if set, are used to authenticate to the
SMTP server, and the :setting:`EMAIL_USE_TLS` setting controls whether a secure
connection is used.
Mail is sent using the SMTP host and port specified in the
:setting:`EMAIL_HOST` and :setting:`EMAIL_PORT` settings. The
:setting:`EMAIL_HOST_USER` and :setting:`EMAIL_HOST_PASSWORD` settings, if
set, are used to authenticate to the SMTP server, and the
:setting:`EMAIL_USE_TLS` setting controls whether a secure connection is used.
.. note::
@@ -42,7 +44,7 @@ send_mail()
The simplest way to send e-mail is using the function
``django.core.mail.send_mail()``. Here's its definition:
.. function:: send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None)
.. function:: send_mail(subject, message, from_email, recipient_list, fail_silently=False, auth_user=None, auth_password=None, connection=None)
The ``subject``, ``message``, ``from_email`` and ``recipient_list`` parameters
are required.
@@ -62,6 +64,10 @@ are required.
* ``auth_password``: The optional password to use to authenticate to the
SMTP server. If this isn't provided, Django will use the value of the
``EMAIL_HOST_PASSWORD`` setting.
* ``connection``: The optional email backend to use to send the mail.
If unspecified, an instance of the default backend will be used.
See the documentation on :ref:`E-mail backends <topic-email-backends>`
for more details.
.. _smtplib docs: http://docs.python.org/library/smtplib.html
@@ -71,26 +77,29 @@ send_mass_mail()
``django.core.mail.send_mass_mail()`` is intended to handle mass e-mailing.
Here's the definition:
.. function:: send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None)
.. function:: send_mass_mail(datatuple, fail_silently=False, auth_user=None, auth_password=None, connection=None)
``datatuple`` is a tuple in which each element is in this format::
(subject, message, from_email, recipient_list)
``fail_silently``, ``auth_user`` and ``auth_password`` have the same functions
as in ``send_mail()``.
as in :meth:`~django.core.mail.send_mail()`.
Each separate element of ``datatuple`` results in a separate e-mail message.
As in ``send_mail()``, recipients in the same ``recipient_list`` will all see
the other addresses in the e-mail messages' "To:" field.
As in :meth:`~django.core.mail.send_mail()`, recipients in the same
``recipient_list`` will all see the other addresses in the e-mail messages'
"To:" field.
send_mass_mail() vs. send_mail()
--------------------------------
The main difference between ``send_mass_mail()`` and ``send_mail()`` is that
``send_mail()`` opens a connection to the mail server each time it's executed,
while ``send_mass_mail()`` uses a single connection for all of its messages.
This makes ``send_mass_mail()`` slightly more efficient.
The main difference between :meth:`~django.core.mail.send_mass_mail()` and
:meth:`~django.core.mail.send_mail()` is that
:meth:`~django.core.mail.send_mail()` opens a connection to the mail server
each time it's executed, while :meth:`~django.core.mail.send_mass_mail()` uses
a single connection for all of its messages. This makes
:meth:`~django.core.mail.send_mass_mail()` slightly more efficient.
mail_admins()
=============
@@ -98,7 +107,7 @@ mail_admins()
``django.core.mail.mail_admins()`` is a shortcut for sending an e-mail to the
site admins, as defined in the :setting:`ADMINS` setting. Here's the definition:
.. function:: mail_admins(subject, message, fail_silently=False)
.. function:: mail_admins(subject, message, fail_silently=False, connection=None)
``mail_admins()`` prefixes the subject with the value of the
:setting:`EMAIL_SUBJECT_PREFIX` setting, which is ``"[Django] "`` by default.
@@ -115,7 +124,7 @@ mail_managers() function
sends an e-mail to the site managers, as defined in the :setting:`MANAGERS`
setting. Here's the definition:
.. function:: mail_managers(subject, message, fail_silently=False)
.. function:: mail_managers(subject, message, fail_silently=False, connection=None)
Examples
========
@@ -145,7 +154,7 @@ scripts generate.
The Django e-mail functions outlined above all protect against header injection
by forbidding newlines in header values. If any ``subject``, ``from_email`` or
``recipient_list`` contains a newline (in either Unix, Windows or Mac style),
the e-mail function (e.g. ``send_mail()``) will raise
the e-mail function (e.g. :meth:`~django.core.mail.send_mail()`) will raise
``django.core.mail.BadHeaderError`` (a subclass of ``ValueError``) and, hence,
will not send the e-mail. It's your responsibility to validate all data before
passing it to the e-mail functions.
@@ -178,41 +187,47 @@ from the request's POST data, sends that to admin@example.com and redirects to
.. _emailmessage-and-smtpconnection:
The EmailMessage and SMTPConnection classes
===========================================
The EmailMessage class
======================
.. versionadded:: 1.0
Django's ``send_mail()`` and ``send_mass_mail()`` functions are actually thin
wrappers that make use of the ``EmailMessage`` and ``SMTPConnection`` classes
in ``django.core.mail``. If you ever need to customize the way Django sends
e-mail, you can subclass these two classes to suit your needs.
Django's :meth:`~django.core.mail.send_mail()` and
:meth:`~django.core.mail.send_mass_mail()` functions are actually thin
wrappers that make use of the :class:`~django.core.mail.EmailMessage` class.
Not all features of the :class:`~django.core.mail.EmailMessage` class are
available through the :meth:`~django.core.mail.send_mail()` and related
wrapper functions. If you wish to use advanced features, such as BCC'ed
recipients, file attachments, or multi-part e-mail, you'll need to create
:class:`~django.core.mail.EmailMessage` instances directly.
.. note::
Not all features of the ``EmailMessage`` class are available through the
``send_mail()`` and related wrapper functions. If you wish to use advanced
features, such as BCC'ed recipients, file attachments, or multi-part
e-mail, you'll need to create ``EmailMessage`` instances directly.
This is a design feature. :meth:`~django.core.mail.send_mail()` and
related functions were originally the only interface Django provided.
However, the list of parameters they accepted was slowly growing over
time. It made sense to move to a more object-oriented design for e-mail
messages and retain the original functions only for backwards
compatibility.
This is a design feature. ``send_mail()`` and related functions were
originally the only interface Django provided. However, the list of
parameters they accepted was slowly growing over time. It made sense to
move to a more object-oriented design for e-mail messages and retain the
original functions only for backwards compatibility.
:class:`~django.core.mail.EmailMessage` is responsible for creating the e-mail
message itself. The :ref:`e-mail backend <topic-email-backends>` is then
responsible for sending the e-mail.
In general, ``EmailMessage`` is responsible for creating the e-mail message
itself. ``SMTPConnection`` is responsible for the network connection side of
the operation. This means you can reuse the same connection (an
``SMTPConnection`` instance) for multiple messages.
For convenience, :class:`~django.core.mail.EmailMessage` provides a simple
``send()`` method for sending a single email. If you need to send multiple
messages, the email backend API :ref:`provides an alternative
<topics-sending-multiple-emails>`.
EmailMessage Objects
--------------------
.. class:: EmailMessage
The ``EmailMessage`` class is initialized with the following parameters (in
the given order, if positional arguments are used). All parameters are
optional and can be set at any time prior to calling the ``send()`` method.
The :class:`~django.core.mail.EmailMessage` class is initialized with the
following parameters (in the given order, if positional arguments are used).
All parameters are optional and can be set at any time prior to calling the
``send()`` method.
* ``subject``: The subject line of the e-mail.
@@ -227,7 +242,7 @@ optional and can be set at any time prior to calling the ``send()`` method.
* ``bcc``: A list or tuple of addresses used in the "Bcc" header when
sending the e-mail.
* ``connection``: An ``SMTPConnection`` instance. Use this parameter if
* ``connection``: An e-mail backend instance. Use this parameter if
you want to use the same connection for multiple messages. If omitted, a
new connection is created when ``send()`` is called.
@@ -248,18 +263,18 @@ For example::
The class has the following methods:
* ``send(fail_silently=False)`` sends the message, using either
the connection that is specified in the ``connection``
attribute, or creating a new connection if none already
exists. If the keyword argument ``fail_silently`` is ``True``,
exceptions raised while sending the message will be quashed.
* ``send(fail_silently=False)`` sends the message. If a connection was
specified when the email was constructed, that connection will be used.
Otherwise, an instance of the default backend will be instantiated and
used. If the keyword argument ``fail_silently`` is ``True``, exceptions
raised while sending the message will be quashed.
* ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
subclass of Python's ``email.MIMEText.MIMEText`` class) or a
``django.core.mail.SafeMIMEMultipart`` object holding the
message to be sent. If you ever need to extend the ``EmailMessage`` class,
you'll probably want to override this method to put the content you want
into the MIME object.
``django.core.mail.SafeMIMEMultipart`` object holding the message to be
sent. If you ever need to extend the
:class:`~django.core.mail.EmailMessage` class, you'll probably want to
override this method to put the content you want into the MIME object.
* ``recipients()`` returns a list of all the recipients of the message,
whether they're recorded in the ``to`` or ``bcc`` attributes. This is
@@ -299,13 +314,13 @@ The class has the following methods:
Sending alternative content types
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It can be useful to include multiple versions of the content in an e-mail;
the classic example is to send both text and HTML versions of a message. With
It can be useful to include multiple versions of the content in an e-mail; the
classic example is to send both text and HTML versions of a message. With
Django's e-mail library, you can do this using the ``EmailMultiAlternatives``
class. This subclass of ``EmailMessage`` has an ``attach_alternative()`` method
for including extra versions of the message body in the e-mail. All the other
methods (including the class initialization) are inherited directly from
``EmailMessage``.
class. This subclass of :class:`~django.core.mail.EmailMessage` has an
``attach_alternative()`` method for including extra versions of the message
body in the e-mail. All the other methods (including the class initialization)
are inherited directly from :class:`~django.core.mail.EmailMessage`.
To send a text and HTML combination, you could write::
@@ -318,41 +333,231 @@ To send a text and HTML combination, you could write::
msg.attach_alternative(html_content, "text/html")
msg.send()
By default, the MIME type of the ``body`` parameter in an ``EmailMessage`` is
``"text/plain"``. It is good practice to leave this alone, because it
guarantees that any recipient will be able to read the e-mail, regardless of
their mail client. However, if you are confident that your recipients can
handle an alternative content type, you can use the ``content_subtype``
attribute on the ``EmailMessage`` class to change the main content type. The
major type will always be ``"text"``, but you can change it to the subtype. For
example::
By default, the MIME type of the ``body`` parameter in an
:class:`~django.core.mail.EmailMessage` is ``"text/plain"``. It is good
practice to leave this alone, because it guarantees that any recipient will be
able to read the e-mail, regardless of their mail client. However, if you are
confident that your recipients can handle an alternative content type, you can
use the ``content_subtype`` attribute on the
:class:`~django.core.mail.EmailMessage` class to change the main content type.
The major type will always be ``"text"``, but you can change it to the
subtype. For example::
msg = EmailMessage(subject, html_content, from_email, [to])
msg.content_subtype = "html" # Main content is now text/html
msg.send()
SMTPConnection Objects
----------------------
.. _topic-email-backends:
.. class:: SMTPConnection
E-Mail Backends
===============
The ``SMTPConnection`` class is initialized with the host, port, username and
password for the SMTP server. If you don't specify one or more of those
options, they are read from your settings file.
.. versionadded:: 1.2
If you're sending lots of messages at once, the ``send_messages()`` method of
the ``SMTPConnection`` class is useful. It takes a list of ``EmailMessage``
instances (or subclasses) and sends them over a single connection. For example,
if you have a function called ``get_notification_email()`` that returns a
list of ``EmailMessage`` objects representing some periodic e-mail you wish to
send out, you could send this with::
The actual sending of an e-mail is handled by the e-mail backend.
connection = SMTPConnection() # Use default settings for connection
The e-mail backend class has the following methods:
* ``open()`` instantiates an long-lived email-sending connection.
* ``close()`` closes the current email-sending connection.
* ``send_messages(email_messages)`` sends a list of
:class:`~django.core.mail.EmailMessage` objects. If the connection is
not open, this call will implicitly open the connection, and close the
connection afterwards. If the connection is already open, it will be
left open after mail has been sent.
Obtaining an instance of an e-mail backend
------------------------------------------
The :meth:`get_connection` function in ``django.core.mail`` returns an
instance of the e-mail backend that you can use.
.. currentmodule:: django.core.mail
.. function:: get_connection(backend=None, fail_silently=False, *args, **kwargs)
By default, a call to ``get_connection()`` will return an instance of the
email backend specified in :setting:`EMAIL_BACKEND`. If you specify the
``backend`` argument, an instance of that backend will be instantiated.
The ``fail_silently`` argument controls how the backend should handle errors.
If ``fail_silently`` is True, exceptions during the email sending process
will be silently ignored.
All other arguments are passed directly to the constructor of the
e-mail backend.
Django ships with several e-mail sending backends. With the exception of the
SMTP backend (which is the default), these backends are only useful during
testing and development. If you have special email sending requirements, you
can :ref:`write your own email backend <topic-custom-email-backend>`.
.. _topic-email-smtp-backend:
SMTP backend
~~~~~~~~~~~~
This is the default backend. E-mail will be sent through a SMTP server.
The server address and authentication credentials are set in the
:setting:`EMAIL_HOST`, :setting:`EMAIL_POST`, :setting:`EMAIL_HOST_USER`,
:setting:`EMAIL_HOST_PASSWORD` and :setting:`EMAIL_USE_TLS` settings in your
settings file.
The SMTP backend is the default configuration inherited by Django. If you
want to specify it explicitly, put the following in your settings::
EMAIL_BACKEND = 'django.core.mail.backends.smtp'
.. admonition:: SMTPConnection objects
Prior to version 1.2, Django provided a
:class:`~django.core.mail.SMTPConnection` class. This class provided a way
to directly control the use of SMTP to send email. This class has been
deprecated in favor of the generic email backend API.
For backwards compatibility :class:`~django.core.mail.SMTPConnection` is
still available in ``django.core.mail`` as an alias for the SMTP backend.
New code should use :meth:`~django.core.mail.get_connection` instead.
Console backend
~~~~~~~~~~~~~~~
Instead of sending out real e-mails the console backend just writes the
e-mails that would be send to the standard output. By default, the console
backend writes to ``stdout``. You can use a different stream-like object by
providing the ``stream`` keyword argument when constructing the connection.
To specify this backend, put the following in your settings::
EMAIL_BACKEND = 'django.core.mail.backends.console'
This backend is not intended for use in production -- it is provided as a
convenience that can be used during development.
File backend
~~~~~~~~~~~~
The file backend writes e-mails to a file. A new file is created for each new
session that is opened on this backend. The directory to which the files are
written is either taken from the :setting:`EMAIL_FILE_PATH` setting or from
the ``file_path`` keyword when creating a connection with
:meth:`~django.core.mail.get_connection`.
To specify this backend, put the following in your settings::
EMAIL_BACKEND = 'django.core.mail.backends.filebased'
EMAIL_FILE_PATH = '/tmp/app-messages' # change this to a proper location
This backend is not intended for use in production -- it is provided as a
convenience that can be used during development.
In-memory backend
~~~~~~~~~~~~~~~~~
The ``'locmem'`` backend stores messages in a special attribute of the
``django.core.mail`` module. The ``outbox`` attribute is created when the
first message is send. It's a list with an
:class:`~django.core.mail.EmailMessage` instance for each message that would
be send.
To specify this backend, put the following in your settings::
EMAIL_BACKEND = 'django.core.mail.backends.locmem'
This backend is not intended for use in production -- it is provided as a
convenience that can be used during development and testing.
Dummy backend
~~~~~~~~~~~~~
As the name suggests the dummy backend does nothing with your messages. To
specify this backend, put the following in your settings::
EMAIL_BACKEND = 'django.core.mail.backends.dummy'
This backend is not intended for use in production -- it is provided as a
convenience that can be used during development.
.. _topic-custom-email-backend:
Defining a custom e-mail backend
--------------------------------
If you need to change how e-mails are send you can write your own e-mail
backend. The ``EMAIL_BACKEND`` setting in your settings file is then the
Python import path for your backend.
Custom e-mail backends should subclass ``BaseEmailBackend`` that is located in
the ``django.core.mail.backends.base`` module. A custom e-mail backend must
implement the ``send_messages(email_messages)`` method. This method receives a
list of :class:`~django.core.mail.EmailMessage` instances and returns the
number of successfully delivered messages. If your backend has any concept of
a persistent session or connection, you should also implement the ``open()``
and ``close()`` methods. Refer to ``SMTPEmailBackend`` for a reference
implementation.
.. _topics-sending-multiple-emails:
Sending multiple emails
-----------------------
Establishing and closing an SMTP connection (or any other network connection,
for that matter) is an expensive process. If you have a lot of emails to send,
it makes sense to reuse an SMTP connection, rather than creating and
destroying a connection every time you want to send an email.
There are two ways you tell an email backend to reuse a connection.
Firstly, you can use the ``send_messages()`` method. ``send_messages()`` takes
a list of :class:`~django.core.mail.EmailMessage` instances (or subclasses),
and sends them all using a single connection.
For example, if you have a function called ``get_notification_email()`` that
returns a list of :class:`~django.core.mail.EmailMessage` objects representing
some periodic e-mail you wish to send out, you could send these emails using
a single call to send_messages::
from django.core import mail
connection = mail.get_connection() # Use default email connection
messages = get_notification_email()
connection.send_messages(messages)
In this example, the call to ``send_messages()`` opens a connection on the
backend, sends the list of messages, and then closes the connection again.
The second approach is to use the ``open()`` and ``close()`` methods on the
email backend to manually control the connection. ``send_messages()`` will not
manually open or close the connection if it is already open, so if you
manually open the connection, you can control when it is closed. For example::
from django.core import mail
connection = mail.get_connection()
# Manually open the connection
connection.open()
# Construct an email message that uses the connection
email1 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
['to1@example.com'], connection=connection)
email1.send() # Send the email
# Construct two more messages
email2 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
['to2@example.com'])
email3 = mail.EmailMessage('Hello', 'Body goes here', 'from@example.com',
['to3@example.com'])
# Send the two emails in a single call -
connection.send_messages([email2, email3])
# The connection was already open so send_messages() doesn't close it.
# We need to manually close the connection.
connection.close()
Testing e-mail sending
----------------------
======================
The are times when you do not want Django to send e-mails at all. For example,
while developing a website, you probably don't want to send out thousands of
@@ -360,19 +565,41 @@ e-mails -- but you may want to validate that e-mails will be sent to the right
people under the right conditions, and that those e-mails will contain the
correct content.
The easiest way to test your project's use of e-mail is to use a "dumb" e-mail
server that receives the e-mails locally and displays them to the terminal,
but does not actually send anything. Python has a built-in way to accomplish
this with a single command::
The easiest way to test your project's use of e-mail is to use the ``console``
email backend. This backend redirects all email to stdout, allowing you to
inspect the content of mail.
The ``file`` email backend can also be useful during development -- this backend
dumps the contents of every SMTP connection to a file that can be inspected
at your leisure.
Another approach is to use a "dumb" SMTP server that receives the e-mails
locally and displays them to the terminal, but does not actually send
anything. Python has a built-in way to accomplish this with a single command::
python -m smtpd -n -c DebuggingServer localhost:1025
This command will start a simple SMTP server listening on port 1025 of
localhost. This server simply prints to standard output all email headers and
the email body. You then only need to set the :setting:`EMAIL_HOST` and
localhost. This server simply prints to standard output all e-mail headers and
the e-mail body. You then only need to set the :setting:`EMAIL_HOST` and
:setting:`EMAIL_PORT` accordingly, and you are set.
For more entailed testing and processing of e-mails locally, see the Python
documentation on the `SMTP Server`_.
For a more detailed discussion of testing and processing of e-mails locally,
see the Python documentation on the `SMTP Server`_.
.. _SMTP Server: http://docs.python.org/library/smtpd.html
SMTPConnection
==============
.. class:: SMTPConnection
.. deprecated:: 1.2
The ``SMTPConnection`` class has been deprecated in favor of the generic email
backend API.
For backwards compatibility ``SMTPConnection`` is still available in
``django.core.mail`` as an alias for the :ref:`SMTP backend
<topic-email-smtp-backend>`. New code should use
:meth:`~django.core.mail.get_connection` instead.

View File

@@ -29,6 +29,7 @@ created by :djadmin:`django-admin.py startproject <startproject>`::
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
)

View File

@@ -40,7 +40,8 @@ algorithm the system follows to determine which Python code to execute:
1. Django determines the root URLconf module to use. Ordinarily,
this is the value of the ``ROOT_URLCONF`` setting, but if the incoming
``HttpRequest`` object has an attribute called ``urlconf``, its value
``HttpRequest`` object has an attribute called ``urlconf`` (set by
middleware :ref:`request processing <request-middleware>`), its value
will be used in place of the ``ROOT_URLCONF`` setting.
2. Django loads that Python module and looks for the variable

View File

@@ -11,7 +11,7 @@ Install Python
Being a Python Web framework, Django requires Python.
It works with any Python version from 2.3 to 2.6 (due to backwards
It works with any Python version from 2.4 to 2.6 (due to backwards
incompatibilities in Python 3.0, Django does not currently work with
Python 3.0; see :ref:`the Django FAQ <faq-install>` for more
information on supported Python versions and the 3.0 transition).
@@ -93,10 +93,10 @@ database bindings are installed.
will also want to read the database-specific notes for the :ref:`MySQL
backend <ref-databases>`.
* If you're using SQLite and either Python 2.3 or Python 2.4, you'll need
pysqlite_. Use version 2.0.3 or higher. Python 2.5 ships with an SQLite
wrapper in the standard library, so you don't need to install anything extra
in that case. Please read the SQLite backend :ref:`notes<sqlite-notes>`.
* If you're using SQLite and Python 2.4, you'll need pysqlite_. Use version
2.0.3 or higher. Python 2.5 ships with an SQLite wrapper in the standard
library, so you don't need to install anything extra in that case. Please
read the SQLite backend :ref:`notes<sqlite-notes>`.
* If you're using Oracle, you'll need a copy of cx_Oracle_, but please
read the database-specific notes for the

View File

@@ -980,19 +980,21 @@ subclass::
def setUp(self):
# Test definitions as before.
call_setup_methods()
def testFluffyAnimals(self):
# A test that uses the fixtures.
call_some_test_code()
Here's specifically what will happen:
* At the start of each test case, before ``setUp()`` is run, Django will
flush the database, returning the database to the state it was in
directly after ``syncdb`` was called.
directly after :djadmin:`syncdb` was called.
* Then, all the named fixtures are installed. In this example, Django will
install any JSON fixture named ``mammals``, followed by any fixture named
``birds``. See the :djadmin:`loaddata documentation<loaddata>` for more
``birds``. See the :djadmin:`loaddata` documentation for more
details on defining and installing fixtures.
This flush/load procedure is repeated for each test in the test case, so you
@@ -1028,6 +1030,7 @@ For example::
def testIndexPageView(self):
# Here you'd test your view using ``Client``.
call_some_test_code()
This test case will use the contents of ``myapp.test_urls`` as the
URLconf for the duration of the test case.
@@ -1104,6 +1107,8 @@ applications:
``target_status_code`` will be the url and status code for the final
point of the redirect chain.
.. _topics-testing-email:
E-mail services
---------------
@@ -1117,7 +1122,7 @@ test every aspect of sending e-mail -- from the number of messages sent to the
contents of each message -- without actually sending the messages.
The test runner accomplishes this by transparently replacing the normal
:class:`~django.core.mail.SMTPConnection` class with a different version.
email backend with a testing backend.
(Don't worry -- this has no effect on any other e-mail senders outside of
Django, such as your machine's mail server, if you're running one.)
@@ -1128,14 +1133,8 @@ Django, such as your machine's mail server, if you're running one.)
During test running, each outgoing e-mail is saved in
``django.core.mail.outbox``. This is a simple list of all
:class:`~django.core.mail.EmailMessage` instances that have been sent.
It does not exist under normal execution conditions, i.e., when you're not
running unit tests. The outbox is created during test setup, along with the
dummy :class:`~django.core.mail.SMTPConnection`. When the test framework is
torn down, the standard :class:`~django.core.mail.SMTPConnection` class is
restored, and the test outbox is destroyed.
The ``outbox`` attribute is a special attribute that is created *only* when
the tests are run. It doesn't normally exist as part of the
the ``locmem`` e-mail backend is used. It doesn't normally exist as part of the
:mod:`django.core.mail` module and you can't import it directly. The code
below shows how to access this attribute correctly.