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:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
-----------
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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_.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
-------------
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
@@ -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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
@@ -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
|
||||
~~~~~
|
||||
|
||||
|
||||
@@ -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
70
docs/releases/1.2.txt
Normal 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.
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
======================================
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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',
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user