summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorChristopher Long <indirecthit@gmail.com>2007-06-17 22:18:54 +0000
committerChristopher Long <indirecthit@gmail.com>2007-06-17 22:18:54 +0000
commitae22b6d403dcf25098c77f0dfcf59ae58b186461 (patch)
treec37fc631e99a7e4d909d6b6d236f495003731ea7 /docs
parent0cf7bc439129c66df8d64601e885f83b256b4f25 (diff)
per-object-permissions: Merged to trunk [5486] NOTE: Not fully tested, will be working on this over the next few weeks.
git-svn-id: http://code.djangoproject.com/svn/django/branches/per-object-permissions@5488 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'docs')
-rw-r--r--docs/add_ons.txt68
-rw-r--r--docs/apache_auth.txt4
-rw-r--r--docs/api_stability.txt46
-rw-r--r--docs/authentication.txt217
-rw-r--r--docs/cache.txt19
-rw-r--r--docs/contributing.txt227
-rw-r--r--docs/databases.txt165
-rw-r--r--docs/databrowse.txt60
-rw-r--r--docs/db-api.txt135
-rw-r--r--docs/design_philosophies.txt2
-rw-r--r--docs/distributions.txt78
-rw-r--r--docs/django-admin.txt192
-rw-r--r--docs/documentation.txt42
-rw-r--r--docs/email.txt101
-rw-r--r--docs/faq.txt33
-rw-r--r--docs/fastcgi.txt55
-rw-r--r--docs/flatpages.txt14
-rw-r--r--docs/forms.txt74
-rw-r--r--docs/generic_views.txt70
-rw-r--r--docs/i18n.txt39
-rw-r--r--docs/install.txt82
-rw-r--r--docs/legacy_databases.txt26
-rw-r--r--docs/man/django-admin.1162
-rw-r--r--docs/middleware.txt17
-rw-r--r--docs/model-api.txt282
-rw-r--r--docs/modpython.txt73
-rw-r--r--docs/newforms.txt1415
-rw-r--r--docs/outputting_csv.txt6
-rw-r--r--docs/outputting_pdf.txt4
-rw-r--r--docs/overview.txt4
-rw-r--r--docs/redirects.txt12
-rw-r--r--docs/release_notes_0.96.txt264
-rw-r--r--docs/request_response.txt125
-rw-r--r--docs/serialization.txt30
-rw-r--r--docs/sessions.txt27
-rw-r--r--docs/settings.txt283
-rw-r--r--docs/sitemaps.txt22
-rw-r--r--docs/sites.txt12
-rw-r--r--docs/static_files.txt6
-rw-r--r--docs/syndication_feeds.txt79
-rw-r--r--docs/templates.txt161
-rw-r--r--docs/templates_python.txt198
-rw-r--r--docs/testing.txt438
-rw-r--r--docs/tutorial01.txt44
-rw-r--r--docs/tutorial02.txt16
-rw-r--r--docs/tutorial03.txt20
-rw-r--r--docs/tutorial04.txt49
-rw-r--r--docs/url_dispatch.txt134
-rw-r--r--docs/webdesign.txt53
49 files changed, 4899 insertions, 786 deletions
diff --git a/docs/add_ons.txt b/docs/add_ons.txt
index 58c01c4fc0..ffc4f7420f 100644
--- a/docs/add_ons.txt
+++ b/docs/add_ons.txt
@@ -1,13 +1,21 @@
-=====================
-The "contrib" add-ons
-=====================
+============================
+The "django.contrib" add-ons
+============================
Django aims to follow Python's `"batteries included" philosophy`_. It ships
with a variety of extra, optional tools that solve common Web-development
problems.
-This code lives in ``django/contrib`` in the Django distribution. Here's a
-rundown of the packages in ``contrib``:
+This code lives in ``django/contrib`` in the Django distribution. This document
+gives a rundown of the packages in ``contrib``, along with any dependencies
+those packages have.
+
+.. admonition:: Note
+
+ For most of these add-ons -- specifically, the add-ons that include either
+ models or template tags -- you'll need to add the package name (e.g.,
+ ``'django.contrib.admin'``) to your ``INSTALLED_APPS`` setting and re-run
+ ``manage.py syncdb``.
.. _"batteries included" philosophy: http://docs.python.org/tut/node12.html#batteries-included
@@ -17,7 +25,9 @@ admin
The automatic Django administrative interface. For more information, see
`Tutorial 2`_.
-.. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/
+.. _Tutorial 2: ../tutorial02/
+
+Requires the auth_ and contenttypes_ contrib packages to be installed.
auth
====
@@ -26,7 +36,7 @@ Django's authentication framework.
See the `authentication documentation`_.
-.. _authentication documentation: http://www.djangoproject.com/documentation/authentication/
+.. _authentication documentation: ../authentication/
comments
========
@@ -46,13 +56,11 @@ A middleware for preventing Cross Site Request Forgeries
See the `csrf documentation`_.
-.. _csrf documentation: http://www.djangoproject.com/documentation/csrf/
+.. _csrf documentation: ../csrf/
formtools
=========
-**New in Django development version**
-
A set of high-level abstractions for Django forms (django.newforms).
django.contrib.formtools.preview
@@ -137,18 +145,38 @@ A framework for managing simple "flat" HTML content in a database.
See the `flatpages documentation`_.
-.. _flatpages documentation: http://www.djangoproject.com/documentation/flatpages/
+.. _flatpages documentation: ../flatpages/
+
+Requires the sites_ contrib package to be installed as well.
+
+localflavor
+===========
+
+A collection of various Django snippets that are useful only for a particular
+country or culture. For example, ``django.contrib.localflavor.usa.forms``
+contains a ``USZipCodeField`` that you can use to validate U.S. zip codes.
markup
======
-A collection of template filters that implement these common markup languages:
+A collection of template filters that implement common markup languages:
+
+ * ``textile`` -- implements `Textile`_
+ * ``markdown`` -- implements `Markdown`_
+ * ``restructuredtext`` -- implements `ReST (ReStructured Text)`_
+
+In each case, the filter expects formatted markup as a string and returns a
+string representing the marked-up text. For example, the ``textile`` filter
+converts text that is marked-up in Textile format to HTML.
- * Textile
- * Markdown
- * ReST (ReStructured Text)
+To activate these filters, add ``'django.contrib.markup'`` to your
+``INSTALLED_APPS`` setting. Once you've done that, use ``{% load markup %}`` in
+a template, and you'll have access to these filters. For more documentation,
+read the source code in django/contrib/markup/templatetags/markup.py.
-For documentation, read the source code in django/contrib/markup/templatetags/markup.py.
+.. _Textile: http://en.wikipedia.org/wiki/Textile_%28markup_language%29
+.. _Markdown: http://en.wikipedia.org/wiki/Markdown
+.. _ReST (ReStructured Text): http://en.wikipedia.org/wiki/ReStructuredText
redirects
=========
@@ -157,7 +185,7 @@ A framework for managing redirects.
See the `redirects documentation`_.
-.. _redirects documentation: http://www.djangoproject.com/documentation/redirects/
+.. _redirects documentation: ../redirects/
sites
=====
@@ -168,7 +196,7 @@ one or more sites.
See the `sites documentation`_.
-.. _sites documentation: http://www.djangoproject.com/documentation/sites/
+.. _sites documentation: ../sites/
sitemaps
========
@@ -177,7 +205,7 @@ A framework for generating Google sitemap XML files.
See the `sitemaps documentation`_.
-.. _sitemaps documentation: http://www.djangoproject.com/documentation/sitemaps/
+.. _sitemaps documentation: ../sitemaps/
syndication
===========
@@ -186,7 +214,7 @@ A framework for generating syndication feeds, in RSS and Atom, quite easily.
See the `syndication documentation`_.
-.. _syndication documentation: http://www.djangoproject.com/documentation/syndication/
+.. _syndication documentation: ../syndication/
Other add-ons
=============
diff --git a/docs/apache_auth.txt b/docs/apache_auth.txt
index b85057924b..583cb96b39 100644
--- a/docs/apache_auth.txt
+++ b/docs/apache_auth.txt
@@ -65,7 +65,7 @@ are equivalent::
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
PythonOption DJANGO_SETTINGS_MODULE mysite.settings
-.. _authentication system: http://www.djangoproject.com/documentation/authentication/
+.. _authentication system: ../authentication/
.. _Subversion: http://subversion.tigris.org/
.. _mod_dav: http://httpd.apache.org/docs/2.0/mod/mod_dav.html
-.. _custom permissions: http://www.djangoproject.com/documentation/authentication/#custom-permissions
+.. _custom permissions: ../authentication/#custom-permissions
diff --git a/docs/api_stability.txt b/docs/api_stability.txt
index 18885fbe63..cfaffeac6b 100644
--- a/docs/api_stability.txt
+++ b/docs/api_stability.txt
@@ -98,26 +98,26 @@ change:
rewrite before Django 1.0. Even if the change isn't quite that drastic,
there will at least be moderate changes.
-.. _caching: http://www.djangoproject.com/documentation/cache/
-.. _custom template tags and libraries: http://www.djangoproject.com/documentation/templates_python/
-.. _database lookup: http://www.djangoproject.com/documentation/db_api/
-.. _django-admin utility: http://www.djangoproject.com/documentation/django_admin/
-.. _fastcgi integration: http://www.djangoproject.com/documentation/fastcgi/
-.. _flatpages: http://www.djangoproject.com/documentation/flatpages/
-.. _generic views: http://www.djangoproject.com/documentation/generic_views/
-.. _internationalization: http://www.djangoproject.com/documentation/i18n/
-.. _legacy database integration: http://www.djangoproject.com/documentation/legacy_databases/
-.. _model definition: http://www.djangoproject.com/documentation/model_api/
-.. _mod_python integration: http://www.djangoproject.com/documentation/modpython/
-.. _redirects: http://www.djangoproject.com/documentation/redirects/
-.. _request/response objects: http://www.djangoproject.com/documentation/request_response/
-.. _sending email: http://www.djangoproject.com/documentation/email/
-.. _sessions: http://www.djangoproject.com/documentation/sessions/
-.. _settings: http://www.djangoproject.com/documentation/settings/
-.. _syndication: http://www.djangoproject.com/documentation/syndication/
-.. _template language: http://www.djangoproject.com/documentation/templates/
-.. _transactions: http://www.djangoproject.com/documentation/transactions/
-.. _url dispatch: http://www.djangoproject.com/documentation/url_dispatch/
-.. _forms and validation: http://www.djangoproject.com/documentation/forms/
-.. _serialization: http://www.djangoproject.com/documentation/serialization/
-.. _authentication: http://www.djangoproject.com/documentation/authentication/
+.. _caching: ../cache/
+.. _custom template tags and libraries: ../templates_python/
+.. _database lookup: ../db-api/
+.. _django-admin utility: ../django-admin/
+.. _fastcgi integration: ../fastcgi/
+.. _flatpages: ../flatpages/
+.. _generic views: ../generic_views/
+.. _internationalization: ../i18n/
+.. _legacy database integration: ../legacy_databases/
+.. _model definition: ../model-api/
+.. _mod_python integration: ../modpython/
+.. _redirects: ../redirects/
+.. _request/response objects: ../request_response/
+.. _sending email: ../email/
+.. _sessions: ../sessions/
+.. _settings: ../settings/
+.. _syndication: ../syndication/
+.. _template language: ../templates/
+.. _transactions: ../transactions/
+.. _url dispatch: ../url_dispatch/
+.. _forms and validation: ../forms/
+.. _serialization: ../serialization/
+.. _authentication: ../authentication/
diff --git a/docs/authentication.txt b/docs/authentication.txt
index 08565e13e1..12b61db538 100644
--- a/docs/authentication.txt
+++ b/docs/authentication.txt
@@ -86,10 +86,10 @@ objects in the same way as any other `Django model`_::
myuser.groups.add(group, group,...)
myuser.groups.remove(group, group,...)
myuser.groups.clear()
- myuser.permissions = [permission_list]
- myuser.permissions.add(permission, permission, ...)
- myuser.permissions.remove(permission, permission, ...]
- myuser.permissions.clear()
+ myuser.user_permissions = [permission_list]
+ myuser.user_permissions.add(permission, permission, ...)
+ myuser.user_permissions.remove(permission, permission, ...]
+ myuser.user_permissions.clear()
In addition to those automatic API methods, ``User`` objects have the following
custom methods:
@@ -144,8 +144,8 @@ custom methods:
Raises ``django.contrib.auth.models.SiteProfileNotAvailable`` if the current site
doesn't allow profiles.
-.. _Django model: http://www.djangoproject.com/documentation/model_api/
-.. _DEFAULT_FROM_EMAIL: http://www.djangoproject.com/documentation/settings/#default-from-email
+.. _Django model: ../model-api/
+.. _DEFAULT_FROM_EMAIL: ../settings/#default-from-email
Manager functions
~~~~~~~~~~~~~~~~~
@@ -204,9 +204,12 @@ The ``password`` attribute of a ``User`` object is a string in this format::
That's hashtype, salt and hash, separated by the dollar-sign character.
-Hashtype is either ``sha1`` (default) or ``md5`` -- the algorithm used to
-perform a one-way hash of the password. Salt is a random string used to salt
-the raw password to create the hash.
+Hashtype is either ``sha1`` (default), ``md5`` or ``crypt`` -- the algorithm
+used to perform a one-way hash of the password. Salt is a random string used
+to salt the raw password to create the hash. Note that the ``crypt`` method is
+only supported on platforms that have the standard Python ``crypt`` module
+available, and ``crypt`` support is only available in the Django development
+version.
For example::
@@ -271,8 +274,8 @@ previous section). You can tell them apart with ``is_authenticated()``, like so:
else:
# Do something for anonymous users.
-.. _request objects: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
-.. _session documentation: http://www.djangoproject.com/documentation/sessions/
+.. _request objects: ../request_response/#httprequest-objects
+.. _session documentation: ../sessions/
How to log a user in
--------------------
@@ -317,6 +320,16 @@ This example shows how you might use both ``authenticate()`` and ``login()``::
else:
# Return an 'invalid login' error message.
+Manually checking a user's password
+-----------------------------------
+
+If you'd like to manually authenticate a user by comparing a
+plain-text password to the hashed password in the database, use the
+convenience function `django.contrib.auth.models.check_password`. It
+takes two arguments: the plain-text password to check, and the full
+value of a user's ``password`` field in the database to check against,
+and returns ``True`` if they match, ``False`` otherwise.
+
How to log a user out
---------------------
@@ -377,27 +390,28 @@ introduced in Python 2.4::
``login_required`` does the following:
- * If the user isn't logged in, redirect to ``/accounts/login/``, passing
- the current absolute URL in the query string as ``next``. For example:
+ * If the user isn't logged in, redirect to ``settings.LOGIN_URL``
+ (``/accounts/login/`` by default), passing the current absolute URL
+ in the query string as ``next``. For example:
``/accounts/login/?next=/polls/3/``.
* If the user is logged in, execute the view normally. The view code is
free to assume the user is logged in.
-Note that you'll need to map the appropriate Django view to ``/accounts/login/``.
-To do this, add the following line to your URLconf::
+Note that you'll need to map the appropriate Django view to ``settings.LOGIN_URL``.
+For example, using the defaults, add the following line to your URLconf::
(r'^accounts/login/$', 'django.contrib.auth.views.login'),
-Here's what ``django.contrib.auth.views.login`` does::
+Here's what ``django.contrib.auth.views.login`` does:
* If called via ``GET``, it displays a login form that POSTs to the same
URL. More on this in a bit.
* If called via ``POST``, it tries to log the user in. If login is
successful, the view redirects to the URL specified in ``next``. If
- ``next`` isn't provided, it redirects to ``/accounts/profile/`` (which is
- currently hard-coded). If login isn't successful, it redisplays the login
- form.
+ ``next`` isn't provided, it redirects to ``settings.LOGIN_REDIRECT_URL``
+ (which defaults to ``/accounts/profile/``). If login isn't successful,
+ it redisplays the login form.
It's your responsibility to provide the login form in a template called
``registration/login.html`` by default. This template gets passed three
@@ -441,8 +455,149 @@ block::
{% endblock %}
-.. _forms documentation: http://www.djangoproject.com/documentation/forms/
-.. _site framework docs: http://www.djangoproject.com/documentation/sites/
+.. _forms documentation: ../forms/
+.. _site framework docs: ../sites/
+
+Other built-in views
+--------------------
+
+In addition to the `login` view, the authentication system includes a
+few other useful built-in views:
+
+``django.contrib.auth.views.logout``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+Logs a user out.
+
+**Optional arguments:**
+
+ * ``template_name``: The full name of a template to display after
+ logging the user out. This will default to
+ ``registration/logged_out.html`` if no argument is supplied.
+
+**Template context:**
+
+ * ``title``: The string "Logged out", localized.
+
+``django.contrib.auth.views.logout_then_login``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+Logs a user out, then redirects to the login page.
+
+**Optional arguments:**
+
+ * ``login_url``: The URL of the login page to redirect to. This
+ will default to ``settings.LOGIN_URL`` if not supplied.
+
+``django.contrib.auth.views.password_change``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+Allows a user to change their password.
+
+**Optional arguments:**
+
+ * ``template_name``: The full name of a template to use for
+ displaying the password change form. This will default to
+ ``registration/password_change_form.html`` if not supplied.
+
+**Template context:**
+
+ * ``form``: The password change form.
+
+``django.contrib.auth.views.password_change_done``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+The page shown after a user has changed their password.
+
+**Optional arguments:**
+
+ * ``template_name``: The full name of a template to use. This will
+ default to ``registration/password_change_done.html`` if not
+ supplied.
+
+``django.contrib.auth.views.password_reset``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+Allows a user to reset their password, and sends them the new password
+in an email.
+
+**Optional arguments:**
+
+ * ``template_name``: The full name of a template to use for
+ displaying the password reset form. This will default to
+ ``registration/password_reset_form.html`` if not supplied.
+
+ * ``email_template_name``: The full name of a template to use for
+ generating the email with the new password. This will default to
+ ``registration/password_reset_email.html`` if not supplied.
+
+**Template context:**
+
+ * ``form``: The form for resetting the user's password.
+
+``django.contrib.auth.views.password_reset_done``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+The page shown after a user has reset their password.
+
+**Optional arguments:**
+
+ * ``template_name``: The full name of a template to use. This will
+ default to ``registration/password_reset_done.html`` if not
+ supplied.
+
+``django.contrib.auth.views.redirect_to_login``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**Description:**
+
+Redirects to the login page, and then back to another URL after a
+successful login.
+
+**Required arguments:**
+
+ * ``next``: The URL to redirect to after a successful login.
+
+**Optional arguments:**
+
+ * ``login_url``: The URL of the login page to redirect to. This
+ will default to ``settings.LOGIN_URL`` if not supplied.
+
+Built-in manipulators
+---------------------
+
+If you don't want to use the built-in views, but want the convenience
+of not having to write manipulators for this functionality, the
+authentication system provides several built-in manipulators:
+
+ * ``django.contrib.auth.forms.AdminPasswordChangeForm``: A
+ manipulator used in the admin interface to change a user's
+ password.
+
+ * ``django.contrib.auth.forms.AuthenticationForm``: A manipulator
+ for logging a user in.
+
+ * ``django.contrib.auth.forms.PasswordChangeForm``: A manipulator
+ for allowing a user to change their password.
+
+ * ``django.contrib.auth.forms.PasswordResetForm``: A manipulator
+ for resetting a user's password and emailing the new password to
+ them.
+
+ * ``django.contrib.auth.forms.UserCreationForm``: A manipulator
+ for creating a new user.
Limiting access to logged-in users that pass a test
---------------------------------------------------
@@ -485,7 +640,7 @@ Note that ``user_passes_test`` does not automatically check that the ``User``
is not anonymous.
``user_passes_test()`` takes an optional ``login_url`` argument, which lets you
-specify the URL for your login page (``/accounts/login/`` by default).
+specify the URL for your login page (``settings.LOGIN_URL`` by default).
Example in Python 2.3 syntax::
@@ -529,7 +684,7 @@ parameter. Example::
my_view = permission_required('polls.can_vote', login_url='/loginpage/')(my_view)
As in the ``login_required`` decorator, ``login_url`` defaults to
-``'/accounts/login/'``.
+``settings.LOGIN_URL``.
Limiting access to generic views
--------------------------------
@@ -544,7 +699,7 @@ For example::
def limited_object_detail(*args, **kwargs):
return object_detail(*args, **kwargs)
-.. _generic view: http://www.djangoproject.com/documentation/generic_views/
+.. _generic view: ../generic_views/
Permissions
===========
@@ -575,7 +730,7 @@ Django developers are currently discussing.
Default permissions
-------------------
-Three basic permissions -- add, create and delete -- are automatically created
+Three basic permissions -- add, change and delete -- are automatically created
for each Django model that has a ``class Admin`` set. Behind the scenes, these
permissions are added to the ``auth_permission`` database table when you run
``manage.py syncdb``.
@@ -606,7 +761,7 @@ This example model creates three custom permissions::
The only thing this does is create those extra permissions when you run
``syncdb``.
-.. _model Meta attribute: http://www.djangoproject.com/documentation/model_api/#meta-options
+.. _model Meta attribute: ../model-api/#meta-options
API reference
-------------
@@ -645,7 +800,7 @@ The currently logged-in user and his/her permissions are made available in the
setting contains ``"django.core.context_processors.auth"``, which is default.
For more, see the `RequestContext docs`_.
- .. _RequestContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-requestcontext
+ .. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext
Users
-----
@@ -691,7 +846,7 @@ Thus, you can check permissions in template ``{% if %}`` statements::
<p>You don't have permission to do anything in the foo app.</p>
{% endif %}
-.. _template context: http://www.djangoproject.com/documentation/templates_python/
+.. _template context: ../templates_python/
Groups
======
@@ -756,7 +911,7 @@ scenes, so any messages will be deleted even if you don't display them.
Finally, note that this messages framework only works with users in the user
database. To send messages to anonymous users, use the `session framework`_.
-.. _session framework: http://www.djangoproject.com/documentation/sessions/
+.. _session framework: ../sessions/
Other authentication sources
============================
@@ -813,13 +968,13 @@ The ``authenticate`` method takes credentials as keyword arguments. Most of
the time, it'll just look like this::
class MyBackend:
- def authenticate(username=None, password=None):
+ def authenticate(self, username=None, password=None):
# Check the username/password and return a User.
But it could also authenticate a token, like so::
class MyBackend:
- def authenticate(token=None):
+ def authenticate(self, token=None):
# Check the token and return a User.
Either way, ``authenticate`` should check the credentials it gets, and it
diff --git a/docs/cache.txt b/docs/cache.txt
index 1795345ed9..e245e100e7 100644
--- a/docs/cache.txt
+++ b/docs/cache.txt
@@ -66,10 +66,19 @@ deleting arbitrary data in the cache. All data is stored directly in memory,
so there's no overhead of database or filesystem usage.
After installing Memcached itself, you'll need to install the Memcached Python
-bindings. They're in a single Python module, memcache.py, available at
-ftp://ftp.tummy.com/pub/python-memcached/ . If that URL is no longer valid,
-just go to the Memcached Web site (http://www.danga.com/memcached/) and get the
-Python bindings from the "Client APIs" section.
+bindings. Two versions of this are available. Choose and install *one* of the
+following modules:
+
+ * The fastest available option is a module called ``cmemcache``, available
+ at http://gijsbert.org/cmemcache/ . (This module is only compatible with
+ the Django development version. Django 0.96 is only compatible with the
+ second option, below.)
+
+ * If you can't install ``cmemcache``, you can install ``python-memcached``,
+ available at ftp://ftp.tummy.com/pub/python-memcached/ . If that URL is
+ no longer valid, just go to the Memcached Web site
+ (http://www.danga.com/memcached/) and get the Python bindings from the
+ "Client APIs" section.
To use Memcached with Django, set ``CACHE_BACKEND`` to
``memcached://ip:port/``, where ``ip`` is the IP address of the Memcached
@@ -250,7 +259,7 @@ Additionally, ``CacheMiddleware`` automatically sets a few headers in each
See the `middleware documentation`_ for more on middleware.
-.. _`middleware documentation`: http://www.djangoproject.com/documentation/middleware/
+.. _`middleware documentation`: ../middleware/
The per-view cache
==================
diff --git a/docs/contributing.txt b/docs/contributing.txt
index de9236f6c1..31409f27bd 100644
--- a/docs/contributing.txt
+++ b/docs/contributing.txt
@@ -122,9 +122,9 @@ Patch style
* Name the patch file with a ``.diff`` extension; this will let the ticket
tracker apply correct syntax highlighting, which is quite helpful.
- * Put the prefix "[patch] " before the title of your ticket. This will make
- it obvious that the ticket includes a patch, and it will add the ticket
- to the `list of tickets with patches`_.
+ * Check the "Has patch" box on the ticket details. This will make it
+ obvious that the ticket includes a patch, and it will add the ticket to
+ the `list of tickets with patches`_.
* The code required to fix a problem or add a feature is an essential part
of a patch, but it is not the only part. A good patch should also include
@@ -151,24 +151,97 @@ Unfortunately, not all bug reports in the `ticket tracker`_ provide all
the `required details`_. A number of tickets have patches, but those patches
don't meet all the requirements of a `good patch`_.
-One way to help out is to *triage* bugs that have been reported by other users.
-Pick an open ticket that is missing some details, and try to replicate the
-problem. Fill in the missing pieces of the report. If the ticket doesn't have
-a patch, create one.
+One way to help out is to *triage* bugs that have been reported by other
+users. A couple of dedicated volunteers work on this regularly, but more help
+is always appreciated.
-Once you've completed all the missing details on the ticket and you have a
-patch with all the required features, e-mail `django-developers`_. Indicate
-that you have triaged a ticket, and recommend a course of action for dealing
-with that ticket.
+Most of the workflow is based around the concept of a ticket's "triage stage".
+This stage describes where in its lifetime a given ticket is at any time.
+Along with a handful of flags, this field easily tells us what and who each
+ticket is waiting on.
-At first, this may require you to be persistent. If you find that your triaged
-ticket still isn't getting attention, occasional polite requests for eyeballs
-to look at your ticket may be necessary. However, as you earn a reputation for
-quality triage work, you should find that it is easier to get the developers'
-attention.
+Since a picture is worth a thousand words, let's start there:
+
+.. image:: http://media.djangoproject.com/img/doc/djangotickets.png
+ :height: 451
+ :width: 590
+ :alt: Django's ticket workflow
+
+We've got two roles here:
+
+ * Core developers: people with commit access who make the decisions and
+ write the bulk of the code.
+
+ * Ticket triagers: community members who keep track of tickets, making
+ sure the tickets are always categorized correctly.
+
+Second, note the four triage stages:
+
+ 1. A ticket starts as "Unreviewed", meaning that a triager has yet to
+ examine the ticket and move it along.
+
+ 2. "Design decision needed" means "this concept requires a design
+ decision," which should be discussed either in the ticket comments or on
+ django-developers.
+
+ 3. Once a ticket is ruled to be approved for fixing, it's moved into the
+ "Accepted" stage. This stage is where all the real work gets done.
+
+ 4. If a ticket has an associated patch (see below), a triager will review the
+ patch. If the patch is complete, it'll be marked as "ready for checkin" so
+ that a core developer knows to review and check in the patches.
+
+The second part of this workflow involves a set of flags the describe what the
+ticket has or needs in order to be "ready for checkin":
+
+ "Has patch"
+ This means the ticket has an associated patch_. These will be
+ reviewed to see if the patch is "good".
+
+ "Needs documentation"
+ This flag is used for tickets with patches that need associated
+ documentation. Complete documentation of features is a prerequisite
+ before we can check a fix into the codebase.
+
+ "Needs tests"
+ This flags the patch as needing associated unit tests. Again, this is a
+ required part of a valid patch.
+
+ "Patch needs improvement"
+ This flag means that although the ticket *has* a patch, it's not quite
+ ready for checkin. This could mean the patch no longer applies
+ cleanly, or that the code doesn't live up to our standards.
+
+A ticket can be resolved in a number of ways:
+
+ "fixed"
+ Used by one of the core developers once a patch has been rolled into
+ Django and the issue is fixed.
+
+ "invalid"
+ Used if the ticket is found to be incorrect or a user error.
+
+ "wontfix"
+ Used when a core developer decides that this request is not
+ appropriate for consideration in Django. This is usually chosen after
+ discussion in the ``django-developers`` mailing list, and you should
+ feel free to join in when it's something you care about.
+
+ "duplicate"
+ Used when another ticket covers the same issue. By closing duplicate
+ tickets, we keep all the discussion in one place, which helps everyone.
+
+ "worksforme"
+ Used when the triage team is unable to replicate the original bug.
+
+If you believe that the ticket was closed in error -- because you're
+still having the issue, or it's popped up somewhere else, or the triagers have
+-- made a mistake, please reopen the ticket and tell us why. Please do not
+reopen tickets that have been marked as "wontfix" by core developers.
.. _required details: `Reporting bugs`_
.. _good patch: `Patch style`_
+.. _patch: `Submitting patches`_
Submitting and maintaining translations
=======================================
@@ -186,7 +259,7 @@ translated, here's what to do:
`i18n documentation`_.
.. _Django i18n mailing list: http://groups.google.com/group/django-i18n/
-.. _i18n documentation: http://www.djangoproject.com/documentation/i18n/
+.. _i18n documentation: ../i18n/
Coding style
============
@@ -206,6 +279,15 @@ Please follow these coding standards when writing code for inclusion in Django:
* Mark all strings for internationalization; see the `i18n documentation`_
for details.
+ * Please don't put your name in the code you contribute. Our policy is to
+ keep contributors' names in the ``AUTHORS`` file distributed with Django
+ -- not scattered throughout the codebase itself. Feel free to include a
+ change to the ``AUTHORS`` file in your patch if you make more than a
+ single trivial change.
+
+Template style
+--------------
+
* In Django template code, put one (and only one) space between the curly
brackets and the tag contents.
@@ -217,6 +299,9 @@ Please follow these coding standards when writing code for inclusion in Django:
{{foo}}
+View style
+----------
+
* In Django views, the first parameter in a view function should be called
``request``.
@@ -230,9 +315,72 @@ Please follow these coding standards when writing code for inclusion in Django:
def my_view(req, foo):
# ...
- * Please don't put your name in the code. While we appreciate all
- contributions to Django, our policy is not to publish individual
- developer names in code -- for instance, at the top of Python modules.
+Model style
+-----------
+
+ * Field names should be all lowercase, using underscores instead of
+ camelCase.
+
+ Do this::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=20)
+ last_name = models.CharField(maxlength=40)
+
+ Don't do this::
+
+ class Person(models.Model):
+ FirstName = models.CharField(maxlength=20)
+ Last_Name = models.CharField(maxlength=40)
+
+ * The ``class Meta`` should appear *after* the fields are defined, with
+ a single blank line separating the fields and the class definition.
+
+ Do this::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=20)
+ last_name = models.CharField(maxlength=40)
+
+ class Meta:
+ verbose_name_plural = 'people'
+
+ Don't do this::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=20)
+ last_name = models.CharField(maxlength=40)
+ class Meta:
+ verbose_name_plural = 'people'
+
+ Don't do this, either::
+
+ class Person(models.Model):
+ class Meta:
+ verbose_name_plural = 'people'
+
+ first_name = models.CharField(maxlength=20)
+ last_name = models.CharField(maxlength=40)
+
+ * The order of model inner classes and standard methods should be as
+ follows (noting that these are not all required):
+
+ * All database fields
+ * ``class Meta``
+ * ``class Admin``
+ * ``def __str__()``
+ * ``def save()``
+ * ``def get_absolute_url()``
+ * Any custom methods
+
+ * If ``choices`` is defined for a given model field, define the choices as
+ a tuple of tuples, with an all-uppercase name, either near the top of the
+ model module or just above the model class. Example::
+
+ GENDER_CHOICES = (
+ ('M', 'Male'),
+ ('F', 'Female'),
+ )
Committing code
===============
@@ -311,7 +459,7 @@ The Django tests all use the testing infrastructure that ships with Django for
testing applications. See `Testing Django applications`_ for an explanation of
how to write new tests.
-.. _Testing Django applications: http://www.djangoproject.com/documentation/testing/
+.. _Testing Django applications: ../testing/
Running the unit tests
----------------------
@@ -321,10 +469,11 @@ To run the tests, ``cd`` to the ``tests/`` directory and type::
./runtests.py --settings=path.to.django.settings
Yes, the unit tests need a settings module, but only for database connection
-info -- the ``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD``.
-You will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just
-needs to be present) and a ``SITE_ID`` setting (any integer value will do) in
-order for all the tests to pass.
+info -- the ``DATABASE_NAME`` (required, but will be ignored),
+``DATABASE_ENGINE``, ``DATABASE_USER`` and ``DATABASE_PASSWORD`` settings. You
+will also need a ``ROOT_URLCONF`` setting (its value is ignored; it just needs
+to be present) and a ``SITE_ID`` setting (any integer value will do) in order
+for all the tests to pass.
The unit tests will not touch your existing databases; they create a new
database, called ``django_test_db``, which is deleted when the tests are
@@ -438,6 +587,29 @@ Alternatively, you can use a symlink called ``django`` that points to the
location of the branch's ``django`` package. If you want to switch back, just
change the symlink to point to the old code.
+A third option is to use a `path file`_ (``<something>.pth``) which should
+work on all systems (including Windows, which doesn't have symlinks
+available). First, make sure there are no files, directories or symlinks named
+``django`` in your ``site-packages`` directory. Then create a text file named
+``django.pth`` and save it to your ``site-packages`` directory. That file
+should contain a path to your copy of Django on a single line and optional
+comments. Here is an example that points to multiple branches. Just uncomment
+the line for the branch you want to use ('Trunk' in this example) and make
+sure all other lines are commented::
+
+ # Trunk is a svn checkout of:
+ # http://code.djangoproject.com/svn/django/trunk/
+ #
+ /path/to/trunk
+
+ # <branch> is a svn checkout of:
+ # http://code.djangoproject.com/svn/django/branches/<branch>/
+ #
+ #/path/to/<branch>
+
+ # On windows a path may look like this:
+ # C:/path/to/<branch>
+
If you're using Django 0.95 or earlier and installed it using
``python setup.py install``, you'll have a directory called something like
``Django-0.95-py2.4.egg`` instead of ``django``. In this case, edit the file
@@ -445,6 +617,8 @@ If you're using Django 0.95 or earlier and installed it using
file. Then copy the branch's version of the ``django`` directory into
``site-packages``.
+.. _path file: http://docs.python.org/lib/module-site.html
+
Official releases
=================
@@ -548,8 +722,7 @@ requests for commit access are potential flame-war starters, and will be ignored
.. _search the tracker: http://code.djangoproject.com/search
.. _django-users: http://groups.google.com/group/django-users
.. _`#django`: irc://irc.freenode.net/django
-.. _list of tickets with patches: http://code.djangoproject.com/report/12
+.. _list of tickets with patches: http://code.djangoproject.com/query?status=new&status=assigned&status=reopened&has_patch=1&order=priority
.. _PEP 8: http://www.python.org/peps/pep-0008.html
-.. _i18n documentation: http://www.djangoproject.com/documentation/i18n/
.. _i18n branch: http://code.djangoproject.com/browser/django/branches/i18n
.. _`tags/releases`: http://code.djangoproject.com/browser/django/tags/releases
diff --git a/docs/databases.txt b/docs/databases.txt
new file mode 100644
index 0000000000..b73f39843c
--- /dev/null
+++ b/docs/databases.txt
@@ -0,0 +1,165 @@
+===============================
+Notes about supported databases
+===============================
+
+Django attempts to support as many features as possible on all database
+backends. However, not all database backends are alike, and we've had to make
+design decisions on which features to support and which assumptions we can make
+safely.
+
+This file describes some of the features that might be relevant to Django
+usage. Of course, it is not intended as a replacement for server-specific
+documentation or reference manuals.
+
+MySQL notes
+===========
+
+Django expects the database to support transactions, referential integrity,
+and Unicode support (UTF-8 encoding). Fortunately, MySQL_ has all these
+features as available as far back as 3.23. While it may be possible to use
+3.23 or 4.0, you'll probably have less trouble if you use 4.1 or 5.0.
+
+MySQL 4.1
+---------
+
+`MySQL 4.1`_ has greatly improved support for character sets. It is possible to
+set different default character sets on the database, table, and column.
+Previous versions have only a server-wide character set setting. It's also the
+first version where the character set can be changed on the fly. 4.1 also has
+support for views, but Django currently doesn't use views.
+
+MySQL 5.0
+---------
+
+`MySQL 5.0`_ adds the ``information_schema`` database, which contains detailed
+data on all database schema. Django's ``inspectdb`` feature uses this
+``information_schema`` if it's available. 5.0 also has support for stored
+procedures, but Django currently doesn't use stored procedures.
+
+.. _MySQL: http://www.mysql.com/
+.. _MySQL 4.1: http://dev.mysql.com/doc/refman/4.1/en/index.html
+.. _MySQL 5.0: http://dev.mysql.com/doc/refman/5.0/en/index.html
+
+Storage engines
+---------------
+
+MySQL has several `storage engines`_ (previously called table types). You can
+change the default storage engine in the server configuration.
+
+The default engine is MyISAM_. The main drawback of MyISAM is that it doesn't
+currently support transactions or foreign keys. On the plus side, it's
+currently the only engine that supports full-text indexing and searching.
+
+The InnoDB_ engine is fully transactional and supports foreign key references.
+
+The BDB_ engine, like InnoDB, is also fully transactional and supports foreign
+key references. However, its use seems to be deprecated.
+
+`Other storage engines`_, including SolidDB_ and Falcon_, are on the horizon.
+For now, InnoDB is probably your best choice.
+
+.. _storage engines: http://dev.mysql.com/doc/refman/5.0/en/storage-engines.html
+.. _MyISAM: http://dev.mysql.com/doc/refman/5.0/en/myisam-storage-engine.html
+.. _BDB: http://dev.mysql.com/doc/refman/5.0/en/bdb-storage-engine.html
+.. _InnoDB: http://dev.mysql.com/doc/refman/5.0/en/innodb.html
+.. _Other storage engines: http://dev.mysql.com/doc/refman/5.1/en/storage-engines-other.html
+.. _SolidDB: http://forge.mysql.com/projects/view.php?id=139
+.. _Falcon: http://dev.mysql.com/doc/falcon/en/index.html
+
+MySQLdb
+-------
+
+`MySQLdb`_ is the Python interface to MySQL. Version 1.2.1p2 or later is
+required for full MySQL support in Django. Earlier versions will not work with
+the ``mysql`` backend.
+
+If you are trying to use an older version of MySQL and the ``mysql_old``
+backend, then 1.2.0 *might* work for you.
+
+.. _MySQLdb: http://sourceforge.net/projects/mysql-python
+
+Creating your database
+----------------------
+
+You can `create your database`_ using the command-line tools and this SQL::
+
+ CREATE DATABASE <dbname> CHARACTER SET utf8;
+
+This ensures all tables and columns will use UTF-8 by default.
+
+.. _create your database: http://dev.mysql.com/doc/refman/5.0/en/create-database.html
+
+Connecting to the database
+--------------------------
+
+Refer to the `settings documentation`_.
+
+Connection settings are used in this order:
+
+ 1. ``DATABASE_OPTIONS``
+ 2. ``DATABASE_NAME``, ``DATABASE_USER``, ``DATABASE_PASSWORD``, ``DATABASE_HOST``,
+ ``DATABASE_PORT``
+ 3. MySQL option files.
+
+In other words, if you set the name of the database in ``DATABASE_OPTIONS``,
+this will take precedence over ``DATABASE_NAME``, which would override
+anything in a `MySQL option file`_.
+
+Here's a sample configuration which uses a MySQL option file::
+
+ # settings.py
+ DATABASE_ENGINE = "mysql"
+ DATABASE_OPTIONS = {
+ 'read_default_file': '/path/to/my.cnf',
+ }
+
+ # my.cnf
+ [client]
+ database = DATABASE_NAME
+ user = DATABASE_USER
+ passwd = DATABASE_PASSWORD
+ default-character-set = utf8
+
+Several other MySQLdb connection options may be useful, such as ``ssl``,
+``use_unicode``, ``init_command``, and ``sql_mode``. Consult the
+`MySQLdb documentation`_ for more details.
+
+.. _settings documentation: http://www.djangoproject.com/documentation/settings/#database-engine
+.. _MySQL option file: http://dev.mysql.com/doc/refman/5.0/en/option-files.html
+.. _MySQLdb documentation: http://mysql-python.sourceforge.net/
+
+Creating your tables
+--------------------
+
+When Django generates the schema, it doesn't specify a storage engine, so
+tables will be created with whatever default storage engine your database
+server is configured for. The easiest solution is to set your database server's
+default storage engine to the desired engine.
+
+If you're using a hosting service and can't change your server's default
+storage engine, you have a couple of options.
+
+ * After the tables are created, execute an ``ALTER TABLE`` statement to
+ convert a table to a new storage engine (such as InnoDB)::
+
+ ALTER TABLE <tablename> ENGINE=INNODB;
+
+ This can be tedious if you have a lot of tables.
+
+ * Another option is to use the ``init_command`` option for MySQLdb prior to
+ creating your tables::
+
+ DATABASE_OPTIONS = {
+ # ...
+ "init_command": "SET storage_engine=INNODB",
+ # ...
+ }
+
+ This sets the default storage engine upon connecting to the database.
+ After your tables have been created, you should remove this option.
+
+ * Another method for changing the storage engine is described in
+ AlterModelOnSyncDB_.
+
+.. _AlterModelOnSyncDB: http://code.djangoproject.com/wiki/AlterModelOnSyncDB
+
diff --git a/docs/databrowse.txt b/docs/databrowse.txt
new file mode 100644
index 0000000000..9c03e7e4ea
--- /dev/null
+++ b/docs/databrowse.txt
@@ -0,0 +1,60 @@
+==========
+Databrowse
+==========
+
+Databrowse is a Django application that lets you browse your data.
+
+As the Django admin dynamically creates an admin interface by introspecting
+your models, Databrowse dynamically creates a rich, browsable Web site by
+introspecting your models.
+
+.. admonition:: Note
+
+ Databrowse is **very** new and is currently under active development. It
+ may change substantially before the next Django release.
+
+ With that said, it's easy to use, and it doesn't require writing any
+ code. So you can play around with it today, with very little investment in
+ time or coding.
+
+How to use Databrowse
+=====================
+
+ 1. Point Django at the default Databrowse templates. There are two ways to
+ do this:
+
+ * Add ``'django.contrib.databrowse'`` to your ``INSTALLED_APPS``
+ setting. This will work if your ``TEMPLATE_LOADERS`` setting includes
+ the ``app_directories`` template loader (which is the case by
+ default). See the `template loader docs`_ for more.
+
+ * Otherwise, determine the full filesystem path to the
+ ``django/contrib/databrowse/templates`` directory, and add that
+ directory to your ``TEMPLATE_DIRS`` setting.
+
+ 2. Register a number of models with the Databrowse site::
+
+ from django.contrib import databrowse
+
+ databrowse.site.register(SomeModel)
+ databrowse.site.register(SomeOtherModel)
+
+ Note that you should register the model *classes*, not instances.
+
+ It doesn't matter where you put this, as long as it gets executed at
+ some point. A good place for it is in your URLconf file (``urls.py``).
+
+ 3. Change your URLconf to import the ``databrowse`` module::
+
+ from django.contrib import databrowse
+
+ ...and add the following line to your URLconf::
+
+ (r'^databrowse/(.*)', databrowse.site.root),
+
+ The prefix doesn't matter -- you can use ``databrowse/`` or ``db/`` or
+ whatever you'd like.
+
+ 4. Run the Django server and visit ``/databrowse/`` in your browser.
+
+.. _template loader docs: ../templates_python/#loader-types
diff --git a/docs/db-api.txt b/docs/db-api.txt
index 13a32bd0b8..e7b8183f6c 100644
--- a/docs/db-api.txt
+++ b/docs/db-api.txt
@@ -6,7 +6,7 @@ Once you've created your `data models`_, Django automatically gives you a
database-abstraction API that lets you create, retrieve, update and delete
objects. This document explains that API.
-.. _`data models`: http://www.djangoproject.com/documentation/model_api/
+.. _`data models`: ../model-api/
Throughout this reference, we'll refer to the following models, which comprise
a weblog application::
@@ -85,7 +85,7 @@ There's no way to tell what the value of an ID will be before you call
unless you explicitly specify ``primary_key=True`` on a field. See the
`AutoField documentation`_.)
-.. _AutoField documentation: http://www.djangoproject.com/documentation/model_api/#autofield
+.. _AutoField documentation: ../model-api/#autofield
Explicitly specifying auto-primary-key values
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -112,7 +112,7 @@ the previous record in the database::
b4 = Blog(id=3, name='Not Cheddar', tagline='Anything but cheese.')
b4.save() # Overrides the previous blog with ID=3!
-See _`How Django knows to UPDATE vs. INSERT`, below, for the reason this
+See `How Django knows to UPDATE vs. INSERT`_, below, for the reason this
happens.
Explicitly specifying auto-primary-key values is mostly useful for bulk-saving
@@ -134,6 +134,15 @@ the database until you explicitly call ``save()``.
The ``save()`` method has no return value.
+Updating ``ForeignKey`` fields works exactly the same way; simply assign an
+object of the right type to the field in question::
+
+ joe = Author.objects.create(name="Joe")
+ entry.author = joe
+ entry.save()
+
+Django will complain if you try to assign an object of the wrong type.
+
How Django knows to UPDATE vs. INSERT
-------------------------------------
@@ -143,8 +152,8 @@ or ``UPDATE`` SQL statements. Specifically, when you call ``save()``, Django
follows this algorithm:
* If the object's primary key attribute is set to a value that evaluates to
- ``True`` (i.e., a value other than ``None`` or the empty string), Django
- executes a ``SELECT`` query to determine whether a record with the given
+ ``True`` (i.e., a value other than ``None`` or the empty string), Django
+ executes a ``SELECT`` query to determine whether a record with the given
primary key already exists.
* If the record with the given primary key does already exist, Django
executes an ``UPDATE`` query.
@@ -379,7 +388,7 @@ The lookup parameters (``**kwargs``) should be in the format described in
`Field lookups`_ below. Multiple parameters are joined via ``AND`` in the
underlying SQL statement, and the whole thing is enclosed in a ``NOT()``.
-This example excludes all entries whose ``pub_date`` is the current date/time
+This example excludes all entries whose ``pub_date`` is later than 2005-1-3
AND whose ``headline`` is "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3), headline='Hello')
@@ -389,8 +398,8 @@ In SQL terms, that evaluates to::
SELECT ...
WHERE NOT (pub_date > '2005-1-3' AND headline = 'Hello')
-This example excludes all entries whose ``pub_date`` is the current date/time
-OR whose ``headline`` is "Hello"::
+This example excludes all entries whose ``pub_date`` is later than 2005-1-3
+AND whose headline is NOT "Hello"::
Entry.objects.exclude(pub_date__gt=datetime.date(2005, 1, 3)).exclude(headline='Hello')
@@ -526,6 +535,21 @@ Examples::
>>> Entry.objects.filter(headline__contains='Lennon').dates('pub_date', 'day')
[datetime.datetime(2005, 3, 20)]
+``none()``
+~~~~~~~~~~
+
+**New in Django development version**
+
+Returns an ``EmptyQuerySet`` -- a ``QuerySet`` that always evaluates to
+an empty list. This can be used in cases where you know that you should
+return an empty result set and your caller is expecting a ``QuerySet``
+object (instead of returning an empty list, for example.)
+
+Examples::
+
+ >>> Entry.objects.none()
+ []
+
``select_related()``
~~~~~~~~~~~~~~~~~~~~
@@ -574,13 +598,28 @@ related ``Person`` *and* the related ``City``::
p = b.author # Doesn't hit the database.
c = p.hometown # Doesn't hit the database.
- sv = Book.objects.get(id=4) # No select_related() in this example.
+ b = Book.objects.get(id=4) # No select_related() in this example.
p = b.author # Hits the database.
c = p.hometown # Hits the database.
Note that ``select_related()`` does not follow foreign keys that have
``null=True``.
+Usually, using ``select_related()`` can vastly improve performance because your
+app can avoid many database calls. However, in situations with deeply nested
+sets of relationships ``select_related()`` can sometimes end up following "too
+many" relations, and can generate queries so large that they end up being slow.
+
+In these situations, you can use the ``depth`` argument to ``select_related()``
+to control how many "levels" of relations ``select_related()`` will actually
+follow::
+
+ b = Book.objects.select_related(depth=1).get(id=4)
+ p = b.author # Doesn't hit the database.
+ c = p.hometown # Requires a database call.
+
+The ``depth`` argument is new in the Django development version.
+
``extra(select=None, where=None, params=None, tables=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -684,7 +723,7 @@ QuerySet methods that do not return QuerySets
The following ``QuerySet`` methods evaluate the ``QuerySet`` and return
something *other than* a ``QuerySet``.
-These methods do not use a cache (see _`Caching and QuerySets` below). Rather,
+These methods do not use a cache (see `Caching and QuerySets`_ below). Rather,
they query the database each time they're called.
``get(**kwargs)``
@@ -876,8 +915,8 @@ The database API supports the following lookup types:
exact
~~~~~
-Exact match. If the value provided for comparison is ``None``, it will
-be interpreted as an SQL ``NULL`` (See isnull_ for more details).
+Exact match. If the value provided for comparison is ``None``, it will
+be interpreted as an SQL ``NULL`` (See isnull_ for more details).
Examples::
@@ -1106,7 +1145,7 @@ such as January 3, July 3, etc.
isnull
~~~~~~
-Takes either ``True`` or ``False``, which correspond to SQL queries of
+Takes either ``True`` or ``False``, which correspond to SQL queries of
``IS NULL`` and ``IS NOT NULL``, respectively.
Example::
@@ -1119,10 +1158,10 @@ SQL equivalent::
.. admonition:: ``__isnull=True`` vs ``__exact=None``
- There is an important difference between ``__isnull=True`` and
+ There is an important difference between ``__isnull=True`` and
``__exact=None``. ``__exact=None`` will *always* return an empty result
- set, because SQL requires that no value is equal to ``NULL``.
- ``__isnull`` determines if the field is currently holding the value
+ set, because SQL requires that no value is equal to ``NULL``.
+ ``__isnull`` determines if the field is currently holding the value
of ``NULL`` without performing a comparison.
search
@@ -1151,7 +1190,7 @@ The pk lookup shortcut
----------------------
For convenience, Django provides a ``pk`` lookup type, which stands for
-"primary_key".
+"primary_key".
In the example ``Blog`` model, the primary key is the ``id`` field, so these
three statements are equivalent::
@@ -1160,14 +1199,14 @@ three statements are equivalent::
Blog.objects.get(id=14) # __exact is implied
Blog.objects.get(pk=14) # pk implies id__exact
-The use of ``pk`` isn't limited to ``__exact`` queries -- any query term
+The use of ``pk`` isn't limited to ``__exact`` queries -- any query term
can be combined with ``pk`` to perform a query on the primary key of a model::
# Get blogs entries with id 1, 4 and 7
Blog.objects.filter(pk__in=[1,4,7])
# Get all blog entries with id > 14
- Blog.objects.filter(pk__gt=14)
-
+ Blog.objects.filter(pk__gt=14)
+
``pk`` lookups also work across joins. For example, these three statements are
equivalent::
@@ -1199,8 +1238,8 @@ whose ``headline`` contains ``'Lennon'``::
Blog.objects.filter(entry__headline__contains='Lennon')
-Escaping parenthesis and underscores in LIKE statements
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Escaping percent signs and underscores in LIKE statements
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The field lookups that equate to ``LIKE`` SQL statements (``iexact``,
``contains``, ``icontains``, ``startswith``, ``istartswith``, ``endswith``
@@ -1606,6 +1645,15 @@ For example, this deletes all ``Entry`` objects with a ``pub_date`` year of
Entry.objects.filter(pub_date__year=2005).delete()
+When Django deletes an object, it emulates the behavior of the SQL
+constraint ``ON DELETE CASCADE`` -- in other words, any objects which
+had foreign keys pointing at the object to be deleted will be deleted
+along with it. For example::
+
+ b = Blog.objects.get(pk=1)
+ # This will delete the Blog and all of its Entry objects.
+ b.delete()
+
Note that ``delete()`` is the only ``QuerySet`` method that is not exposed on a
``Manager`` itself. This is a safety mechanism to prevent you from accidentally
requesting ``Entry.objects.delete()``, and deleting *all* the entries. If you
@@ -1704,6 +1752,47 @@ For every ``ImageField``, the object will have ``get_FOO_height()`` and
``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This
returns the height (or width) of the image, as an integer, in pixels.
+Shortcuts
+=========
+
+As you develop views, you will discover a number of common idioms in the
+way you use the database API. Django encodes some of these idioms as
+shortcuts that can be used to simplify the process of writing views. These
+functions are in the ``django.shortcuts`` module.
+
+get_object_or_404()
+-------------------
+
+One common idiom to use ``get()`` and raise ``Http404`` if the
+object doesn't exist. This idiom is captured by ``get_object_or_404()``.
+This function takes a Django model as its first argument and an
+arbitrary number of keyword arguments, which it passes to the manager's
+``get()`` function. It raises ``Http404`` if the object doesn't
+exist. For example::
+
+ # Get the Entry with a primary key of 3
+ e = get_object_or_404(Entry, pk=3)
+
+When you provide a model to this shortcut function, the default manager
+is used to execute the underlying ``get()`` query. If you don't want to
+use the default manager, or if you want to search a list of related objects,
+you can provide ``get_object_or_404()`` with a manager object instead.
+For example::
+
+ # Get the author of blog instance `e` with a name of 'Fred'
+ a = get_object_or_404(e.authors, name='Fred')
+
+ # Use a custom manager 'recent_entries' in the search for an
+ # entry with a primary key of 3
+ e = get_object_or_404(Entry.recent_entries, pk=3)
+
+get_list_or_404()
+-----------------
+
+``get_list_or_404`` behaves the same way as ``get_object_or_404()``
+-- except that it uses ``filter()`` instead of ``get()``. It raises
+``Http404`` if the list is empty.
+
Falling back to raw SQL
=======================
@@ -1722,4 +1811,4 @@ interface to your database. You can access your database via other tools,
programming languages or database frameworks; there's nothing Django-specific
about your database.
-.. _Executing custom SQL: http://www.djangoproject.com/documentation/model_api/#executing-custom-sql
+.. _Executing custom SQL: ../model-api/#executing-custom-sql
diff --git a/docs/design_philosophies.txt b/docs/design_philosophies.txt
index 7fdc7ea01b..72aa8ade95 100644
--- a/docs/design_philosophies.txt
+++ b/docs/design_philosophies.txt
@@ -186,7 +186,7 @@ code.
This is the philosophy behind `template inheritance`_.
-.. _template inheritance: http://www.djangoproject.com/documentation/templates/#template-inheritance
+.. _template inheritance: ../templates/#template-inheritance
Be decoupled from HTML
----------------------
diff --git a/docs/distributions.txt b/docs/distributions.txt
new file mode 100644
index 0000000000..4ec265f93c
--- /dev/null
+++ b/docs/distributions.txt
@@ -0,0 +1,78 @@
+===================================
+Third-party distributions of Django
+===================================
+
+Several third-party distributors are now providing versions of Django integrated
+with their package-management systems. These can make installation and upgrading
+much easier for users of Django since the integration includes the ability to
+automatically install dependancies (like database adapters) that Django
+requires.
+
+Typically, these packages are based on the latest stable release of Django, so
+if you want to use the development version of Django you'll need to follow the
+instructions for `installing the development version`_ from our Subversion
+repository.
+
+.. _installing the development version: ../install/#installing-the-development-version
+
+Linux distributions
+===================
+
+Debian
+------
+
+A `packaged version of Django`_ is available for `Debian GNU/Linux`_, and can be
+installed from either the "testing" or the "unstable" repositories by typing
+``apt-get install python-django``.
+
+When you install this package, ``apt`` will recommend installing a database
+adapter; you should select and install the adapter for whichever database you
+plan to use with Django.
+
+.. _Debian GNU/Linux: http://www.debian.org/
+.. _packaged version of Django: http://packages.debian.org/testing/python/python-django
+
+Ubuntu
+------
+
+The Debian ``python-django`` package is also available for `Ubuntu Linux`_, in
+the "universe" repository for Ubuntu 7.04 ("Feisty Fawn"). The `current Ubuntu
+package`_ is also based on Django 0.95.1 and can be installed in the same
+fashion as for Debian.
+
+.. _Ubuntu Linux: http://www.ubuntu.com/
+.. _current Ubuntu package: http://packages.ubuntu.com/feisty/python/python-django
+
+Fedora
+------
+
+A Django package is available for `Fedora Linux`_, in the "Fedora Extras"
+repository. The `current Fedora package`_ is based on Django 0.96, and can be
+installed by typing ``yum install Django``. The previous link is for the i386
+binary. Users of other architectures should be able to use that as a starting
+point to find their preferred version.
+
+.. _Fedora Linux: http://fedora.redhat.com/
+.. _current Fedora package: http://download.fedora.redhat.com/pub/fedora/linux/extras/6/i386/repoview/Django.html
+
+Gentoo
+------
+
+A Django build is available for `Gentoo Linux`_, and is based on Django 0.96.
+The `current Gentoo build`_ can be installed by typing ``emerge django``.
+
+.. _Gentoo Linux: http://www.gentoo.org/
+.. _current Gentoo build: http://packages.gentoo.org/packages/?category=dev-python;name=django
+
+For distributors
+================
+
+If you'd like to package Django for distribution, we'd be happy to help out!
+Please join the `django-developers mailing list`_ and introduce yourself.
+
+We also encourage all distributors to subscribe to the `django-announce mailing
+list`_, which is a (very) low-traffic list for announcing new releases of Django
+and important bugfixes.
+
+.. _django-developers mailing list: http://groups.google.com/group/django-developers/
+.. _django-announce mailing list: http://groups.google.com/group/django-announce/
diff --git a/docs/django-admin.txt b/docs/django-admin.txt
index 7f9682b443..d20db7edc9 100644
--- a/docs/django-admin.txt
+++ b/docs/django-admin.txt
@@ -17,13 +17,21 @@ two things for you before delegating to ``django-admin.py``:
The ``django-admin.py`` script should be on your system path if you installed
Django via its ``setup.py`` utility. If it's not on your path, you can find it in
``site-packages/django/bin`` within your Python installation. Consider
-symlinking to it from some place on your path, such as ``/usr/local/bin``.
+symlinking it from some place on your path, such as ``/usr/local/bin``.
+
+For Windows users, who do not have symlinking functionality available, you
+can copy ``django-admin.py`` to a location on your existing path or edit the
+``PATH`` settings (under ``Settings - Control Panel - System - Advanced - Environment...``)
+to point to its installed location.
Generally, when working on a single Django project, it's easier to use
``manage.py``. Use ``django-admin.py`` with ``DJANGO_SETTINGS_MODULE``, or the
``--settings`` command line option, if you need to switch between multiple
Django settings files.
+The command-line examples throughout this document use ``django-admin.py`` to
+be consistent, but any example can use ``manage.py`` just as well.
+
Usage
=====
@@ -53,7 +61,7 @@ Prints the admin-index template snippet for the given appnames.
Use admin-index template snippets if you want to customize the look and feel of
your admin's index page. See `Tutorial 2`_ for more information.
-.. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/
+.. _Tutorial 2: ../tutorial02/
createcachetable [tablename]
----------------------------
@@ -61,7 +69,7 @@ createcachetable [tablename]
Creates a cache table named ``tablename`` for use with the database cache
backend. See the `cache documentation`_ for more information.
-.. _cache documentation: http://www.djangoproject.com/documentation/cache/
+.. _cache documentation: ../cache/
dbshell
-------
@@ -92,6 +100,30 @@ 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 [appname appname ...]
+------------------------------
+
+Output to standard output all data in the database associated with the named
+application(s).
+
+By default, the database will be dumped in JSON format. If you want the output
+to be in another format, use the ``--format`` option (e.g., ``format=xml``).
+You may specify any Django serialization backend (including any user specified
+serialization backends named in the ``SERIALIZATION_MODULES`` setting). The
+``--indent`` option can be used to pretty-print the output.
+
+If no application name is provided, all installed applications will be dumped.
+
+The output of ``dumpdata`` can be used as input for ``loaddata``.
+
+flush
+-----
+
+Return 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.
+
inspectdb
---------
@@ -133,10 +165,87 @@ needed.
``inspectdb`` works with PostgreSQL, MySQL and SQLite. Foreign-key detection
only works in PostgreSQL and with certain types of MySQL tables.
-install [appname appname ...]
------------------------------
+loaddata [fixture fixture ...]
+------------------------------
+
+Searches for and loads the contents of the named fixture into the database.
+
+A *Fixture* is a collection of files that contain the serialized contents of
+the database. Each fixture has a unique name; however, the files that
+comprise the fixture can be distributed over multiple directories, in
+multiple applications.
+
+Django will search in three locations for fixtures:
+
+ 1. In the ``fixtures`` directory of every installed application
+ 2. In any directory named in the ``FIXTURE_DIRS`` setting
+ 3. In the literal path named by the fixture
+
+Django will load any and all fixtures it finds in these locations that match
+the provided fixture names.
+
+If the named fixture has a file extension, only fixtures of that type
+will be loaded. For example::
+
+ django-admin.py loaddata mydata.json
+
+would only load JSON fixtures called ``mydata``. The fixture extension
+must correspond to the registered name of a serializer (e.g., ``json`` or
+``xml``).
+
+If you omit the extension, Django will search all available fixture types
+for a matching fixture. For example::
+
+ django-admin.py loaddata mydata
+
+would look for any fixture of any fixture type called ``mydata``. If a fixture
+directory contained ``mydata.json``, that fixture would be loaded
+as a JSON fixture. However, if two fixtures with the same name but different
+fixture type are discovered (for example, if ``mydata.json`` and
+``mydata.xml`` were found in the same fixture directory), fixture
+installation will be aborted, and any data installed in the call to
+``loaddata`` will be removed from the database.
+
+The fixtures that are named can include directory components. These
+directories will be included in the search path. For example::
+
+ django-admin.py loaddata foo/bar/mydata.json
+
+would search ``<appname>/fixtures/foo/bar/mydata.json`` for each installed
+application, ``<dirname>/foo/bar/mydata.json`` for each directory in
+``FIXTURE_DIRS``, and the literal path ``foo/bar/mydata.json``.
+
+Note that the order in which fixture files are processed is undefined. However,
+all fixture data is installed as a single transaction, so data in
+one fixture can reference data in another fixture. If the database backend
+supports row-level constraints, these constraints will be checked at the
+end of the transaction.
+
+The ``dumpdata`` command can be used to generate input for ``loaddata``.
+
+.. admonition:: MySQL and Fixtures
+
+ Unfortunately, MySQL isn't capable of completely supporting all the
+ features of Django fixtures. If you use MyISAM tables, MySQL doesn't
+ support transactions or constraints, so you won't get a rollback if
+ multiple transaction files are found, or validation of fixture data.
+ If you use InnoDB tables, you won't be able to have any forward
+ references in your data files - MySQL doesn't provide a mechanism to
+ defer checking of row constraints until a transaction is committed.
+
+reset [appname appname ...]
+---------------------------
+Executes the equivalent of ``sqlreset`` for the given appnames.
+
+runfcgi [options]
+-----------------
+Starts a set of FastCGI processes suitable for use with any web server
+which supports the FastCGI protocol. See the `FastCGI deployment
+documentation`_ for details. Requires the Python FastCGI module from
+`flup`_.
-Executes the equivalent of ``sqlall`` for the given appnames.
+.. _FastCGI deployment documentation: ../fastcgi/
+.. _flup: http://www.saddi.com/software/flup/
runserver [optional port number, or ipaddr:port]
------------------------------------------------
@@ -186,11 +295,11 @@ Serving static files with the development server
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
By default, the development server doesn't serve any static files for your site
-(such as CSS files, images, things under ``MEDIA_ROOT_URL`` and so forth). If
+(such as CSS files, images, things under ``MEDIA_URL`` and so forth). If
you want to configure Django to serve static media, read the `serving static files`_
documentation.
-.. _serving static files: http://www.djangoproject.com/documentation/static_files/
+.. _serving static files: ../static_files/
Turning off auto-reload
~~~~~~~~~~~~~~~~~~~~~~~
@@ -223,7 +332,7 @@ sqlall [appname appname ...]
Prints the CREATE TABLE and initial-data SQL statements for the given appnames.
-Refer to the description of ``sqlinitialdata`` for an explanation of how to
+Refer to the description of ``sqlcustom`` for an explanation of how to
specify initial data.
sqlclear [appname appname ...]
@@ -231,27 +340,29 @@ sqlclear [appname appname ...]
Prints the DROP TABLE SQL statements for the given appnames.
-sqlindexes [appname appname ...]
-----------------------------------------
-
-Prints the CREATE INDEX SQL statements for the given appnames.
+sqlcustom [appname appname ...]
+-------------------------------
-sqlinitialdata [appname appname ...]
---------------------------------------------
-
-Prints the initial INSERT SQL statements for the given appnames.
+Prints the custom SQL statements for the given appnames.
For each model in each specified app, this command looks for the file
``<appname>/sql/<modelname>.sql``, where ``<appname>`` is the given appname and
``<modelname>`` is the model's name in lowercase. For example, if you have an
-app ``news`` that includes a ``Story`` model, ``sqlinitialdata`` will attempt
+app ``news`` that includes a ``Story`` model, ``sqlcustom`` will attempt
to read a file ``news/sql/story.sql`` and append it to the output of this
command.
Each of the SQL files, if given, is expected to contain valid SQL. The SQL
files are piped directly into the database after all of the models'
-table-creation statements have been executed. Use this SQL hook to populate
-tables with any necessary initial records, SQL functions or test data.
+table-creation statements have been executed. Use this SQL hook to make any
+table modifications, or insert any SQL functions into the database.
+
+Note that the order in which the SQL files are processed is undefined.
+
+sqlindexes [appname appname ...]
+----------------------------------------
+
+Prints the CREATE INDEX SQL statements for the given appnames.
sqlreset [appname appname ...]
--------------------------------------
@@ -261,7 +372,7 @@ Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.
sqlsequencereset [appname appname ...]
----------------------------------------------
-Prints the SQL statements for resetting PostgreSQL sequences for the given
+Prints the SQL statements for resetting sequences for the given
appnames.
See http://simon.incutio.com/archive/2004/04/21/postgres for more information.
@@ -292,11 +403,14 @@ this command to install the default apps.
If you're installing the ``django.contrib.auth`` application, ``syncdb`` will
give you the option of creating a superuser immediately.
+``syncdb`` will also search for and install any fixture named ``initial_data``
+with an appropriate extension (e.g. ``json`` or ``xml``). See the
+documentation for ``loaddata`` for details on the specification of fixture
+data files.
+
test
----
-**New in Django development version**
-
Discover and run tests for all installed models. See `Testing Django applications`_ for more information.
.. _testing django applications: ../testing/
@@ -341,17 +455,36 @@ setting the Python path for you.
.. _import search path: http://diveintopython.org/getting_to_know_python/everything_is_an_object.html
+--format
+--------
+
+Example usage::
+
+ django-admin.py dumpdata --format=xml
+
+Specifies the output format that will be used. The name provided must be the name
+of a registered serializer.
+
--help
------
Displays a help message that includes a terse list of all available actions and
options.
+--indent
+--------
+
+Example usage::
+
+ django-admin.py dumpdata --indent=4
+
+Specifies the number of spaces that will be used for indentation when
+pretty-printing output. By default, output will *not* be pretty-printed.
+Pretty-printing will only be enabled if the indent option is provided.
+
--noinput
---------
-**New in Django development version**
-
Inform django-admin that the user should NOT be prompted for any input. Useful
if the django-admin script will be executed as an unattended, automated
script.
@@ -374,23 +507,20 @@ Example output::
--verbosity
-----------
-**New in Django development version**
-
Example usage::
django-admin.py syncdb --verbosity=2
-Verbosity determines the amount of notification and debug information that
+Verbosity determines the amount of notification and debug information that
will be printed to the console. '0' is no output, '1' is normal output,
and `2` is verbose output.
--adminmedia
------------
-**New in Django development version**
-
Example usage::
- django-admin.py manage.py --adminmedia=/tmp/new-admin-style/
+
+ django-admin.py --adminmedia=/tmp/new-admin-style/
Tells Django where to find the various CSS and JavaScript files for the admin
interface when running the development server. Normally these files are served
diff --git a/docs/documentation.txt b/docs/documentation.txt
index bacfb176b1..decb066fa1 100644
--- a/docs/documentation.txt
+++ b/docs/documentation.txt
@@ -42,25 +42,25 @@ On the Web
The most recent version of the Django documentation lives at
http://www.djangoproject.com/documentation/ . These HTML pages are generated
-automatically from the text files in source control every 15 minutes. That
-means they reflect the "latest and greatest" in Django -- they include the very
-latest corrections and additions, and they discuss the latest Django features,
+automatically from the text files in source control. That means they reflect
+the "latest and greatest" in Django -- they include the very latest
+corrections and additions, and they discuss the latest Django features,
which may only be available to users of the Django development version. (See
"Differences between versions" below.)
-A key advantage of the Web-based documentation is the comment section at the
-bottom of each document. This is an area for anybody to submit changes,
-corrections and suggestions about the given document. The Django developers
-frequently monitor the comments there and use them to improve the documentation
-for everybody.
+We encourage you to help improve the docs by submitting changes, corrections
+and suggestions in the `ticket system`_. The Django developers actively monitor
+the ticket system and use your feedback to improve the documentation for
+everybody.
-We encourage you to help improve the docs: it's easy! Note, however, that
-comments should explicitly relate to the documentation, rather than asking
-broad tech-support questions. If you need help with your particular Django
-setup, try the `django-users mailing list`_ instead of posting a comment to the
-documentation.
+Note, however, that tickets should explicitly relate to the documentation,
+rather than asking broad tech-support questions. If you need help with your
+particular Django setup, try the `django-users mailing list`_ or the
+`#django IRC channel`_ instead.
+.. _ticket system: http://code.djangoproject.com/simpleticket?component=Documentation
.. _django-users mailing list: http://groups.google.com/group/django-users
+.. _#django IRC channel: irc://irc.freenode.net/django
In plain text
-------------
@@ -94,12 +94,10 @@ Formatting
The text documentation is written in ReST (ReStructured Text) format. That
means it's easy to read but is also formatted in a way that makes it easy to
-convert into other formats, such as HTML. If you're interested, the script that
-converts the ReST text docs into djangoproject.com's HTML lives at
-`djangoproject.com/django_website/apps/docs/parts/build_documentation.py`_ in
-the Django Subversion repository.
+convert into other formats, such as HTML. If you have the `reStructuredText`_
+library installed, you can use ``rst2html`` to generate your own HTML files.
-.. _djangoproject.com/django_website/apps/docs/parts/build_documentation.py: http://code.djangoproject.com/browser/djangoproject.com/django_website/apps/docs/parts/build_documentation.py
+.. _reStructuredText: http://docutils.sourceforge.net/rst.html
Differences between versions
============================
@@ -134,14 +132,6 @@ We follow this policy:
frozen document that says "These docs are frozen for Django version XXX"
and links to the current version of that document.
- * Once a document is frozen for a Django release, we remove comments from
- that page, in favor of having comments on the latest version of that
- document. This is for the sake of maintainability and usability, so that
- users have one, and only one, place to leave comments on a particular
- document. We realize that some people may be stuck on a previous version
- of Django, but we believe the usability problems with multiple versions
- of a document the outweigh the benefits.
-
* The `main documentation Web page`_ includes links to documentation for
all previous versions.
diff --git a/docs/email.txt b/docs/email.txt
index 37a4f38a5e..66948e5294 100644
--- a/docs/email.txt
+++ b/docs/email.txt
@@ -19,13 +19,23 @@ 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 `EMAIL_HOST`_ and
+`EMAIL_PORT`_ settings. The `EMAIL_HOST_USER`_ and `EMAIL_HOST_PASSWORD`_
+settings, if set, are used to authenticate to the SMTP server, and the
+`EMAIL_USE_TLS`_ setting controls whether a secure connection is used.
+
.. note::
- The character set of email sent with ``django.core.mail`` will be set to
+ The character set of e-mail sent with ``django.core.mail`` will be set to
the value of your `DEFAULT_CHARSET setting`_.
-
-.. _DEFAULT_CHARSET setting: ../settings/#DEFAULT_CHARSET
+
+.. _DEFAULT_CHARSET setting: ../settings/#default-charset
+.. _EMAIL_HOST: ../settings/#email-host
+.. _EMAIL_PORT: ../settings/#email-port
+.. _EMAIL_HOST_USER: ../settings/#email-host-user
+.. _EMAIL_HOST_PASSWORD: ../settings/#email-host-password
+.. _EMAIL_USE_TLS: ../settings/#email-use-tls
send_mail()
===========
@@ -34,8 +44,8 @@ The simplest way to send e-mail is using the function
``django.core.mail.send_mail()``. Here's its definition::
send_mail(subject, message, from_email, recipient_list,
- fail_silently=False, auth_user=EMAIL_HOST_USER,
- auth_password=EMAIL_HOST_PASSWORD)
+ fail_silently=False, auth_user=None,
+ auth_password=None)
The ``subject``, ``message``, ``from_email`` and ``recipient_list`` parameters
are required.
@@ -65,7 +75,7 @@ send_mass_mail()
Here's the definition::
send_mass_mail(datatuple, fail_silently=False,
- auth_user=EMAIL_HOST_USER, auth_password=EMAIL_HOST_PASSWORD):
+ auth_user=None, auth_password=None):
``datatuple`` is a tuple in which each element is in this format::
@@ -101,9 +111,9 @@ The "From:" header of the e-mail will be the value of the `SERVER_EMAIL setting`
This method exists for convenience and readability.
-.. _ADMINS setting: http://www.djangoproject.com/documentation/settings/#admins
-.. _EMAIL_SUBJECT_PREFIX setting: http://www.djangoproject.com/documentation/settings/#email-subject-prefix
-.. _SERVER_EMAIL setting: http://www.djangoproject.com/documentation/settings/#server-email
+.. _ADMINS setting: ../settings/#admins
+.. _EMAIL_SUBJECT_PREFIX setting: ../settings/#email-subject-prefix
+.. _SERVER_EMAIL setting: ../settings/#server-email
mail_managers() function
========================
@@ -114,7 +124,7 @@ Here's the definition::
mail_managers(subject, message, fail_silently=False)
-.. _MANAGERS setting: http://www.djangoproject.com/documentation/settings/#managers
+.. _MANAGERS setting: ../settings/#managers
Examples
========
@@ -174,3 +184,72 @@ from the request's POST data, sends that to admin@example.com and redirects to
return HttpResponse('Make sure all fields are entered and valid.')
.. _Header injection: http://securephp.damonkohler.com/index.php/Email_Injection
+
+The EmailMessage and SMTPConnection classes
+===========================================
+
+**New in Django development version**
+
+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.
+
+.. 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 or multi-part e-mail, you'll need to
+ create ``EmailMessage`` instances directly.
+
+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.
+
+The ``EmailMessage`` class is initialized as follows::
+
+ email = EmailMessage(subject, body, from_email, to, bcc, connection)
+
+All of these parameters are optional. If ``from_email`` is omitted, the value
+from ``settings.DEFAULT_FROM_EMAIL`` is used. Both the ``to`` and ``bcc``
+parameters are lists of addresses, as strings.
+
+For example::
+
+ email = EmailMessage('Hello', 'Body goes here', 'from@example.com',
+ ['to1@example.com', 'to2@example.com'],
+ ['bcc@example.com'])
+
+The class has the following methods:
+
+ * ``send()`` sends the message, using either the connection that is
+ specified in the ``connection`` attribute, or creating a new connection
+ if none already exists.
+
+ * ``message()`` constructs a ``django.core.mail.SafeMIMEText`` object (a
+ sub-class of Python's ``email.MIMEText.MIMEText`` class) 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 wish
+ 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
+ another method you might need to override when sub-classing, because the
+ SMTP server needs to be told the full list of recipients when the message
+ is sent. If you add another way to specify recipients in your class, they
+ need to be returned from this method as well.
+
+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.
+
+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::
+
+ connection = SMTPConnection() # Use default settings for connection
+ messages = get_notification_email()
+ connection.send_messages(messages)
diff --git a/docs/faq.txt b/docs/faq.txt
index eaccc6be43..bdd8c5360e 100644
--- a/docs/faq.txt
+++ b/docs/faq.txt
@@ -63,7 +63,7 @@ at any level -- database servers, caching servers or Web/application servers.
The framework cleanly separates components such as its database layer and
application layer. And it ships with a simple-yet-powerful `cache framework`_.
-.. _`cache framework`: http://www.djangoproject.com/documentation/cache/
+.. _`cache framework`: ../cache/
Who's behind this?
------------------
@@ -191,7 +191,7 @@ Like we said: We're picky.
We've documented our philosophies on the `design philosophies page`_.
-.. _design philosophies page: http://www.djangoproject.com/documentation/design_philosophies/
+.. _design philosophies page: ../design_philosophies/
Do you have any of those nifty "screencast" things?
---------------------------------------------------
@@ -277,9 +277,9 @@ How do I get started?
run into trouble.
.. _`Download the code`: http://www.djangoproject.com/download/
-.. _`installation guide`: http://www.djangoproject.com/documentation/install/
-.. _tutorial: http://www.djangoproject.com/documentation/tutorial1/
-.. _documentation: http://www.djangoproject.com/documentation/
+.. _`installation guide`: ../install/
+.. _tutorial: ../tutorial01/
+.. _documentation: ../
.. _ask questions: http://www.djangoproject.com/community/
How do I fix the "install a later version of setuptools" error?
@@ -328,8 +328,9 @@ Do I have to use mod_python?
Although we recommend mod_python for production use, you don't have to use it,
thanks to the fact that Django uses an arrangement called WSGI_. Django can
-talk to any WSGI-enabled server. The most common non-mod_python deployment
-setup is FastCGI. See `How to use Django with FastCGI`_ for full information.
+talk to any WSGI-enabled server. Other non-mod_python deployment setups are
+FastCGI, SCGI or AJP. See `How to use Django with FastCGI, SCGI or AJP`_ for
+full information.
Also, see the `server arrangements wiki page`_ for other deployment strategies.
@@ -337,7 +338,7 @@ If you just want to play around and develop things on your local computer, use
the development Web server that comes with Django. Things should Just Work.
.. _WSGI: http://www.python.org/peps/pep-0333.html
-.. _How to use Django with FastCGI: http://www.djangoproject.com/documentation/fastcgi/
+.. _How to use Django with FastCGI, SCGI or AJP: ../fastcgi/
.. _server arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements
How do I install mod_python on Windows?
@@ -381,9 +382,9 @@ Why do I get an error about importing DJANGO_SETTINGS_MODULE?
Make sure that:
* The environment variable DJANGO_SETTINGS_MODULE is set to a fully-qualified
- Python module (i.e. "mysite.settings.main").
+ Python module (i.e. "mysite.settings").
- * Said module is on ``sys.path`` (``import mysite.settings.main`` should work).
+ * Said module is on ``sys.path`` (``import mysite.settings`` should work).
* The module doesn't contain syntax errors (of course).
@@ -464,7 +465,7 @@ Can I use Django with a pre-existing database?
Yes. See `Integrating with a legacy database`_.
-.. _`Integrating with a legacy database`: http://www.djangoproject.com/documentation/legacy_databases/
+.. _`Integrating with a legacy database`: ../legacy_databases/
If I make changes to a model, how do I update the database?
-----------------------------------------------------------
@@ -511,7 +512,7 @@ type, create an initial data file and put something like this in it::
As explained in the `SQL initial data file`_ documentation, this SQL file can
contain arbitrary SQL, so you can make any sorts of changes you need to make.
-.. _SQL initial data file: http://www.djangoproject.com/documentation/model_api/#providing-initial-sql-data
+.. _SQL initial data file: ../model-api/#providing-initial-sql-data
Why is Django leaking memory?
-----------------------------
@@ -592,7 +593,7 @@ My admin-site CSS and images showed up fine using the development server, but th
See `serving the admin files`_ in the "How to use Django with mod_python"
documentation.
-.. _serving the admin files: http://www.djangoproject.com/documentation/modpython/#serving-the-admin-files
+.. _serving the admin files: ../modpython/#serving-the-admin-files
My "list_filter" contains a ManyToManyField, but the filter doesn't display.
----------------------------------------------------------------------------
@@ -630,7 +631,7 @@ site is built using semantic HTML and plenty of CSS hooks, so any changes you'd
like to make should be possible by editing the stylesheet. We've got a
`guide to the CSS used in the admin`_ to get you started.
-.. _`guide to the CSS used in the admin`: http://www.djangoproject.com/documentation/admin_css/
+.. _`guide to the CSS used in the admin`: ../admin_css/
How do I create users without having to edit password hashes?
-------------------------------------------------------------
@@ -640,7 +641,7 @@ development version, where this problem was fixed on Aug. 4, 2006.
You can also use the Python API. See `creating users`_ for full info.
-.. _creating users: http://www.djangoproject.com/documentation/authentication/#creating-users
+.. _creating users: ../authentication/#creating-users
Contributing code
=================
@@ -651,7 +652,7 @@ How can I get started contributing code to Django?
Thanks for asking! We've written an entire document devoted to this question.
It's titled `Contributing to Django`_.
-.. _Contributing to Django: http://www.djangoproject.com/documentation/contributing/
+.. _Contributing to Django: ../contributing/
I submitted a bug fix in the ticket system several weeks ago. Why are you ignoring my patch?
--------------------------------------------------------------------------------------------
diff --git a/docs/fastcgi.txt b/docs/fastcgi.txt
index e2f4e933b4..81888bba76 100644
--- a/docs/fastcgi.txt
+++ b/docs/fastcgi.txt
@@ -1,11 +1,17 @@
-==============================
-How to use Django with FastCGI
-==============================
+===========================================
+How to use Django with FastCGI, SCGI or AJP
+===========================================
Although the `current preferred setup`_ for running Django is Apache_ with
-`mod_python`_, many people use shared hosting, on which FastCGI is the only
-viable option. In some setups, FastCGI also allows better security -- and,
-possibly, better performance -- than mod_python.
+`mod_python`_, many people use shared hosting, on which protocols such as
+FastCGI, SCGI or AJP are the only viable options. In some setups, these protocols
+also allow better security -- and, possibly, better performance -- than mod_python.
+
+.. admonition:: Note
+
+ This document primarily focuses on FastCGI. Other protocols, such as SCGI
+ and AJP, are also supported, through the ``flup`` Python package. See the
+ "Protocols" section below for specifics about SCGI and AJP.
Essentially, FastCGI is an efficient way of letting an external application
serve pages to a Web server. The Web server delegates the incoming Web requests
@@ -17,7 +23,7 @@ served with no startup time. Unlike mod_python (or `mod_perl`_), a FastCGI
process doesn't run inside the Web server process, but in a separate,
persistent process.
-.. _current preferred setup: http://www.djangoproject.com/documentation/modpython/
+.. _current preferred setup: ../modpython/
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
@@ -74,10 +80,26 @@ your ``manage.py`` is), and then run ``manage.py`` with the ``runfcgi`` option::
If you specify ``help`` as the only option after ``runfcgi``, it'll display a
list of all the available options.
-You'll need to specify either a ``socket`` or both ``host`` and ``port``. Then,
-when you set up your Web server, you'll just need to point it at the host/port
+You'll need to specify either a ``socket``, ``protocol`` or both ``host`` and ``port``.
+Then, when you set up your Web server, you'll just need to point it at the host/port
or socket you specified when starting the FastCGI server.
+Protocols
+---------
+
+Django supports all the protocols that flup_ does, namely fastcgi_, `SCGI`_ and
+`AJP1.3`_ (the Apache JServ Protocol, version 1.3). Select your preferred
+protocol by using the ``protocol=<protocol_name>`` option with
+``./manage.py runfcgi`` -- where ``<protocol_name>`` may be one of: ``fcgi``
+(the default), ``scgi`` or ``ajp``. For example::
+
+ ./manage.py runfcgi --protocol=scgi
+
+.. _flup: http://www.saddi.com/software/flup/
+.. _fastcgi: http://www.fastcgi.com/
+.. _SCGI: http://python.ca/scgi/protocol.txt
+.. _AJP1.3: http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
+
Examples
--------
@@ -181,7 +203,7 @@ This is probably the most common case, if you're using Django's admin site::
DocumentRoot /home/user/public_html
Alias /media /home/user/python/django/contrib/admin/media
RewriteEngine On
- RewriteRule ^/(media.*)$ /$1 [QSA,L]
+ RewriteRule ^/(media.*)$ /$1 [QSA,L,PT]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/(.*)$ /mysite.fcgi/$1 [QSA,L]
</VirtualHost>
@@ -274,7 +296,7 @@ In your Web root directory, add this to a file named ``.htaccess`` ::
Then, create a small script that tells Apache how to spawn your FastCGI
program. Create a file ``mysite.fcgi`` and place it in your Web directory, and
-be sure to make it executable ::
+be sure to make it executable::
#!/usr/bin/python
import sys, os
@@ -304,3 +326,14 @@ If you have access to a command shell on a Unix system, you can accomplish this
easily by using the ``touch`` command::
touch mysite.fcgi
+
+Serving admin media files
+=========================
+
+Regardless of the server and configuration you eventually decide to use, you will
+also need to give some thought to how to serve the admin media files. The
+advice given in the modpython_ documentation is also applicable in the setups
+detailed above.
+
+.. _modpython: ../modpython/#serving-the-admin-files
+
diff --git a/docs/flatpages.txt b/docs/flatpages.txt
index 06979f7a9a..1422f16b6b 100644
--- a/docs/flatpages.txt
+++ b/docs/flatpages.txt
@@ -29,8 +29,8 @@ To install the flatpages app, follow these steps:
to your MIDDLEWARE_CLASSES_ setting.
3. Run the command ``manage.py syncdb``.
-.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
-.. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
+.. _INSTALLED_APPS: ../settings/#installed-apps
+.. _MIDDLEWARE_CLASSES: ../settings/#middleware-classes
How it works
============
@@ -63,9 +63,9 @@ resort.
For more on middleware, read the `middleware docs`_.
-.. _SITE_ID: http://www.djangoproject.com/documentation/settings/#site-id
-.. _RequestContext: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
-.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
+.. _SITE_ID: ../settings/#site-id
+.. _RequestContext: ../templates_python/#subclassing-context-djangocontext
+.. _middleware docs: ../middleware/
How to add, change and delete flatpages
=======================================
@@ -84,9 +84,9 @@ Flatpages are represented by a standard `Django model`_, which lives in
`django/contrib/flatpages/models.py`_. You can access flatpage objects via the
`Django database API`_.
-.. _Django model: http://www.djangoproject.com/documentation/model_api/
+.. _Django model: ../model-api/
.. _django/contrib/flatpages/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/flatpages/models.py
-.. _Django database API: http://www.djangoproject.com/documentation/db_api/
+.. _Django database API: ../db-api/
Flatpage templates
==================
diff --git a/docs/forms.txt b/docs/forms.txt
index 6efa24d28f..f6cb55a3f6 100644
--- a/docs/forms.txt
+++ b/docs/forms.txt
@@ -14,7 +14,7 @@ use the django.newforms system, which we have begun to document in the
If you have legacy form/manipulator code, read the "Migration plan" section in
that document to understand how we're making the switch.
-.. _newforms documentation: http://www.djangoproject.com/documentation/newforms/
+.. _newforms documentation: ../newforms/
Introduction
============
@@ -173,10 +173,10 @@ creation view that takes validation into account::
# Check for validation errors
errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
if errors:
return render_to_response('places/errors.html', {'errors': errors})
else:
- manipulator.do_html2python(new_data)
new_place = manipulator.save(new_data)
return HttpResponse("Place created: %s" % new_place)
@@ -229,10 +229,10 @@ Below is the finished view::
# Check for errors.
errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
if not errors:
# No errors. This means we can save the data!
- manipulator.do_html2python(new_data)
new_place = manipulator.save(new_data)
# Redirect to the object's "edit" page. Always use a redirect
@@ -324,8 +324,8 @@ about editing an existing one? It's shockingly similar to creating a new one::
if request.method == 'POST':
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
if not errors:
- manipulator.do_html2python(new_data)
manipulator.save(new_data)
# Do a post-after-redirect so that reload works, etc.
@@ -406,8 +406,8 @@ Here's a simple function that might drive the above form::
if request.method == 'POST':
new_data = request.POST.copy()
errors = manipulator.get_validation_errors(new_data)
+ manipulator.do_html2python(new_data)
if not errors:
- manipulator.do_html2python(new_data)
# Send e-mail using new_data here...
@@ -417,6 +417,27 @@ Here's a simple function that might drive the above form::
form = forms.FormWrapper(manipulator, new_data, errors)
return render_to_response('contact_form.html', {'form': form})
+Implementing ``flatten_data`` for custom manipulators
+------------------------------------------------------
+
+It is possible (although rarely needed) to replace the default automatically
+created manipulators on a model with your own custom manipulators. If you do
+this and you are intending to use those models in generic views, you should
+also define a ``flatten_data`` method in any ``ChangeManipulator`` replacement.
+This should act like the default ``flatten_data`` and return a dictionary
+mapping field names to their values, like so::
+
+ def flatten_data(self):
+ obj = self.original_object
+ return dict(
+ from = obj.from,
+ subject = obj.subject,
+ ...
+ )
+
+In this way, your new change manipulator will act exactly like the default
+version.
+
``FileField`` and ``ImageField`` special cases
==============================================
@@ -496,10 +517,10 @@ to put punctuation at the end of your validation messages.
When are validators called?
---------------------------
-After a form has been submitted, Django first checks to see that all the
-required fields are present and non-empty. For each field that passes that
-test *and if the form submission contained data* for that field, all the
-validators for that field are called in turn. The emphasized portion in the
+After a form has been submitted, Django validates each field in turn. First,
+if the field is required, Django checks that it is present and non-empty. Then,
+if that test passes *and the form submission contained data* for that field, all
+the validators for that field are called in turn. The emphasized portion in the
last sentence is important: if a form field is not submitted (because it
contains no data -- which is normal HTML behavior), the validators are not
run against the field.
@@ -546,6 +567,7 @@ check for the given property:
* isValidANSIDate
* isValidANSITime
* isValidEmail
+ * isValidFloat
* isValidImage
* isValidImageURL
* isValidPhone
@@ -594,20 +616,28 @@ fails. If no message is passed in, a default message is used.
``other_value``, then the validators in ``validator_list`` are all run
against the current field.
+``RequiredIfOtherFieldGiven``
+ Takes a field name of the current field is only required if the other
+ field has a value.
+
+``RequiredIfOtherFieldsGiven``
+ Similar to ``RequiredIfOtherFieldGiven``, except that it takes a list of
+ field names and if any one of the supplied fields has a value provided,
+ the current field being validated is required.
+
``RequiredIfOtherFieldNotGiven``
Takes the name of the other field and this field is only required if the
other field has no value.
-``RequiredIfOtherFieldsNotGiven``
- Similar to ``RequiredIfOtherFieldNotGiven``, except that it takes a list
- of field names and if any one of the supplied fields does not have a value
- provided, the field being validated is required.
-
``RequiredIfOtherFieldEquals`` and ``RequiredIfOtherFieldDoesNotEqual``
Each of these validator classes takes a field name and a value (in that
order). If the given field does (or does not have, in the latter case) the
given value, then the current field being validated is required.
+ An optional ``other_label`` argument can be passed which, if given, is used
+ in error messages instead of the value. This allows more user friendly error
+ messages if the value itself is not descriptive enough.
+
Note that because validators are called before any ``do_html2python()``
functions, the value being compared against is a string. So
``RequiredIfOtherFieldEquals('choice', '1')`` is correct, whilst
@@ -625,8 +655,8 @@ fails. If no message is passed in, a default message is used.
``NumberIsInRange``
Takes two boundary numbers, ``lower`` and ``upper``, and checks that the
field is greater than ``lower`` (if given) and less than ``upper`` (if
- given).
-
+ given).
+
Both checks are inclusive. That is, ``NumberIsInRange(10, 20)`` will allow
values of both 10 and 20. This validator only checks numeric values
(e.g., float and integer values).
@@ -635,10 +665,10 @@ fails. If no message is passed in, a default message is used.
Takes an integer argument and when called as a validator, checks that the
field being validated is a power of the integer.
-``IsValidFloat``
+``IsValidDecimal``
Takes a maximum number of digits and number of decimal places (in that
- order) and validates whether the field is a float with less than the
- maximum number of digits and decimal place.
+ order) and validates whether the field is a decimal with no more than the
+ maximum number of digits and decimal places.
``MatchesRegularExpression``
Takes a regular expression (a string) as a parameter and validates the
@@ -665,6 +695,6 @@ fails. If no message is passed in, a default message is used.
the executable specified in the ``JING_PATH`` setting (see the settings_
document for more details).
-.. _`generic views`: http://www.djangoproject.com/documentation/generic_views/
-.. _`models API`: http://www.djangoproject.com/documentation/model_api/
-.. _settings: http://www.djangoproject.com/documentation/settings/
+.. _`generic views`: ../generic_views/
+.. _`models API`: ../model-api/
+.. _settings: ../settings/
diff --git a/docs/generic_views.txt b/docs/generic_views.txt
index 25635f35d8..359a82506a 100644
--- a/docs/generic_views.txt
+++ b/docs/generic_views.txt
@@ -44,7 +44,7 @@ simple weblog app that drives the blog on djangoproject.com::
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/(?P<day>\w{1,2})/$', 'archive_day', info_dict),
(r'^(?P<year>\d{4})/(?P<month>[a-z]{3})/$', 'archive_month', info_dict),
(r'^(?P<year>\d{4})/$', 'archive_year', info_dict),
- (r'^/?$', 'archive_index', info_dict),
+ (r'^$', 'archive_index', info_dict),
)
As you can see, this URLconf defines a few options in ``info_dict``.
@@ -71,7 +71,7 @@ are first evaluated, so if you want to pass in a QuerySet via
``extra_context`` that is always fresh you need to wrap it in a function or
lambda that returns the QuerySet.
-.. _database API docs: http://www.djangoproject.com/documentation/db_api/
+.. _database API docs: ../db-api/
"Simple" generic views
======================
@@ -97,9 +97,11 @@ which is a dictionary of the parameters captured in the URL.
* ``extra_context``: A dictionary of values to add to the template
context. By default, this is an empty dictionary. If a value in the
dictionary is callable, the generic view will call it
- just before rendering the template. (**This is new in the
- Django development version.**)
-
+ just before rendering the template.
+
+ * ``mimetype``: The MIME type to use for the resulting document. Defaults
+ to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
+
**Example:**
Given the following URL patterns::
@@ -205,11 +207,11 @@ If ``template_name`` isn't specified, this view will use the template
``<app_label>/<model_name>_archive.html`` by default, where:
* ``<model_name>`` is your model's name in all lowercase. For a model
- ``StaffMember``, that'd be ``staffmember``.
+ ``StaffMember``, that'd be ``staffmember``.
* ``<app_label>`` is the right-most part of the full Python path to
- your model's app. For example, if your model lives in
- ``apps/blog/models.py``, that'd be ``blog``.
+ your model's app. For example, if your model lives in
+ ``apps/blog/models.py``, that'd be ``blog``.
**Template context:**
@@ -223,7 +225,7 @@ In addition to ``extra_context``, the template's context will be:
by ``date_field``. For example, if ``num_latest`` is ``10``, then
``latest`` will be a list of the latest 10 objects in ``queryset``.
-.. _RequestContext docs: http://www.djangoproject.com/documentation/templates_python/#subclassing-context-djangocontext
+.. _RequestContext docs: ../templates_python/#subclassing-context-requestcontext
``django.views.generic.date_based.archive_year``
------------------------------------------------
@@ -266,9 +268,9 @@ to ``True``.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``. The
- view will append ``'_list'`` to the value of this parameter in
- determining the variable's name.
+ to use in the template context. By default, this is ``'object'``. The
+ view will append ``'_list'`` to the value of this parameter in
+ determining the variable's name.
* ``make_object_list``: A boolean specifying whether to retrieve the full
list of objects for this year and pass those to the template. If ``True``,
@@ -360,9 +362,9 @@ date in the *future* are not displayed unless you set ``allow_future`` to
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``. The
- view will append ``'_list'`` to the value of this parameter in
- determining the variable's name.
+ to use in the template context. By default, this is ``'object'``. The
+ view will append ``'_list'`` to the value of this parameter in
+ determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -441,9 +443,9 @@ in the *future* are not displayed unless you set ``allow_future`` to ``True``.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``. The
- view will append ``'_list'`` to the value of this parameter in
- determining the variable's name.
+ to use in the template context. By default, this is ``'object'``. The
+ view will append ``'_list'`` to the value of this parameter in
+ determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -526,9 +528,9 @@ you set ``allow_future`` to ``True``.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``. The
- view will append ``'_list'`` to the value of this parameter in
- determining the variable's name.
+ to use in the template context. By default, this is ``'object'``. The
+ view will append ``'_list'`` to the value of this parameter in
+ determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -638,7 +640,7 @@ future, the view will throw a 404 error by default, unless you set
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``.
+ to use in the template context. By default, this is ``'object'``.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -686,7 +688,7 @@ A page representing a list of objects.
* ``paginate_by``: An integer specifying how many objects should be
displayed per page. If this is given, the view will paginate objects with
``paginate_by`` objects per page. The view will expect either a ``page``
- query string parameter (via ``GET``) containing a zero-indexed page
+ query string parameter (via ``GET``) containing a 1-based page
number, or a ``page`` variable specified in the URLconf. See
"Notes on pagination" below.
@@ -710,9 +712,9 @@ A page representing a list of objects.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``. The
- view will append ``'_list'`` to the value of this parameter in
- determining the variable's name.
+ to use in the template context. By default, this is ``'object'``. The
+ view will append ``'_list'`` to the value of this parameter in
+ determining the variable's name.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -752,6 +754,12 @@ If the results are paginated, the context will contain these extra variables:
* ``previous``: The previous page number, as an integer. This is 1-based.
+ * `last_on_page`: The number of the
+ last result on the current page. This is 1-based.
+
+ * `first_on_page`: The number of the
+ first result on the current page. This is 1-based.
+
* ``pages``: The total number of pages, as an integer.
* ``hits``: The total number of objects across *all* pages, not just this
@@ -824,7 +832,7 @@ A page representing an individual object.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``.
+ to use in the template context. By default, this is ``'object'``.
* ``mimetype``: The MIME type to use for the resulting document. Defaults
to the value of the ``DEFAULT_CONTENT_TYPE`` setting.
@@ -916,8 +924,8 @@ In addition to ``extra_context``, the template's context will be:
See the `manipulator and formfield documentation`_ for more information
about using ``FormWrapper`` objects in templates.
-.. _authentication system: http://www.djangoproject.com/documentation/authentication/
-.. _manipulator and formfield documentation: http://www.djangoproject.com/documentation/forms/
+.. _authentication system: ../authentication/
+.. _manipulator and formfield documentation: ../forms/
``django.views.generic.create_update.update_object``
----------------------------------------------------
@@ -973,7 +981,7 @@ object. This uses the automatic manipulators that come with Django models.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``.
+ to use in the template context. By default, this is ``'object'``.
**Template name:**
@@ -1054,7 +1062,7 @@ contain a form that POSTs to the same URL.
the view's template. See the `RequestContext docs`_.
* ``template_object_name``: Designates the name of the template variable
- to use in the template context. By default, this is ``'object'``.
+ to use in the template context. By default, this is ``'object'``.
**Template name:**
diff --git a/docs/i18n.txt b/docs/i18n.txt
index 4d0d92b082..27abadacc9 100644
--- a/docs/i18n.txt
+++ b/docs/i18n.txt
@@ -53,7 +53,7 @@ internationalization machinery. See the `documentation for USE_I18N`_.
You'll probably also want to remove ``'django.core.context_processors.i18n'``
from your ``TEMPLATE_CONTEXT_PROCESSORS`` setting.
-.. _documentation for USE_I18N: http://www.djangoproject.com/documentation/settings/#use-i18n
+.. _documentation for USE_I18N: ../settings/#use-i18n
How to specify translation strings
==================================
@@ -175,7 +175,7 @@ class, though::
verbose_name = _('my thing')
verbose_name_plural = _('mythings')
-.. _Django models: http://www.djangoproject.com/documentation/model_api/
+.. _Django models: ../model-api/
Pluralization
~~~~~~~~~~~~~
@@ -236,7 +236,7 @@ To pluralize, specify both the singular and plural forms with the
``{% plural %}`` tag, which appears within ``{% blocktrans %}`` and
``{% endblocktrans %}``. Example::
- {% blocktrans count list|count as counter %}
+ {% blocktrans count list|length as counter %}
There is only one {{ name }} object.
{% plural %}
There are {{ counter }} {{ name }} objects.
@@ -274,7 +274,7 @@ translation string. Example::
In this case, both the tag and the filter will see the already-translated
string, so they don't need to be aware of translations.
-.. _Django templates: http://www.djangoproject.com/documentation/templates_python/
+.. _Django templates: ../templates_python/
How to create language files
============================
@@ -282,6 +282,17 @@ How to create language files
Once you've tagged your strings for later translation, you need to write (or
obtain) the language translations themselves. Here's how that works.
+.. admonition:: Locale restrictions
+
+ Django does not support localizing your application into a locale for
+ which Django itself has not been translated. In this case, it will ignore
+ your translation files. If you were to try this and Django supported it,
+ you would inevitably see a mixture of translated strings (from your
+ application) and English strings (from Django itself). If you want to
+ support a locale for your application that is not already part of
+ Django, you'll need to make at least a minimal translation of the Django
+ core.
+
Message files
-------------
@@ -299,7 +310,7 @@ To create or update a message file, run this command::
...where ``de`` is the language code for the message file you want to create.
The language code, in this case, is in locale format. For example, it's
-``pt_BR`` for Brazilian and ``de_AT`` for Austrian German.
+``pt_BR`` for Brazilian Portugese and ``de_AT`` for Austrian German.
The script should be run from one of three places:
@@ -394,7 +405,7 @@ That's it. Your translations are ready for use.
please let us know! See `Submitting and maintaining translations`_ for
the steps to take.
- .. _Submitting and maintaining translations: http://www.djangoproject.com/documentation/contributing/
+ .. _Submitting and maintaining translations: ../contributing/
How Django discovers language preference
========================================
@@ -452,8 +463,8 @@ following this algorithm:
Notes:
* In each of these places, the language preference is expected to be in the
- standard language format, as a string. For example, Brazilian is
- ``pt-br``.
+ standard language format, as a string. For example, Brazilian Portugese
+ is ``pt-br``.
* If a base language is available but the sublanguage specified is not,
Django uses the base language. For example, if a user specifies ``de-at``
(Austrian German) but Django only has ``de`` available, Django uses
@@ -472,7 +483,7 @@ Notes:
selection to German and English (and any sublanguage, like de-ch or
en-us).
- .. _LANGUAGES setting: http://www.djangoproject.com/documentation/settings/#languages
+ .. _LANGUAGES setting: ../settings/#languages
* If you define a custom ``LANGUAGES`` setting, as explained in the
previous bullet, it's OK to mark the languages as translation strings
@@ -530,10 +541,10 @@ Note that, with static (middleware-less) translation, the language is in
``settings.LANGUAGE_CODE``, while with dynamic (middleware) translation, it's
in ``request.LANGUAGE_CODE``.
-.. _settings file: http://www.djangoproject.com/documentation/settings/
-.. _middleware documentation: http://www.djangoproject.com/documentation/middleware/
-.. _session: http://www.djangoproject.com/documentation/sessions/
-.. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
+.. _settings file: ../settings/
+.. _middleware documentation: ../middleware/
+.. _session: ../sessions/
+.. _request object: ../request_response/#httprequest-objects
The ``set_language`` redirect view
==================================
@@ -599,7 +610,7 @@ message file. The choice is yours.
of the settings file to determine this, and a settings file doesn't exist
if you're manually configuring your settings.)
-.. _settings documentation: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
+.. _settings documentation: ../settings/#using-settings-without-the-django-settings-module-environment-variable
All message file repositories are structured the same way. They are:
diff --git a/docs/install.txt b/docs/install.txt
index ff8e1a8318..4f5a4bbe31 100644
--- a/docs/install.txt
+++ b/docs/install.txt
@@ -11,8 +11,8 @@ Being a Python Web framework, Django requires Python.
It works with any Python version 2.3 and higher.
-Get Python at www.python.org. If you're running Linux or Mac OS X, you probably
-already have it installed.
+Get Python at http://www.python.org. If you're running Linux or Mac OS X, you
+probably already have it installed.
Install Apache and mod_python
=============================
@@ -38,33 +38,68 @@ each platform.
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _WSGI: http://www.python.org/peps/pep-0333.html
-.. _How to use Django with mod_python: http://www.djangoproject.com/documentation/modpython/
+.. _How to use Django with mod_python: ../modpython/
.. _server-arrangements wiki page: http://code.djangoproject.com/wiki/ServerArrangements
Get your database running
=========================
If you plan to use Django's database API functionality, you'll need to
-make sure a database server is running. Django works with PostgreSQL_
-(recommended), MySQL_ and SQLite_.
+make sure a database server is running. Django works with PostgreSQL_,
+MySQL_ and SQLite_.
Additionally, you'll need to make sure your Python database bindings are
installed.
-* If you're using PostgreSQL, you'll need the psycopg_ package (version 1.1 --
- not version 1.0 or version 2, which is still in beta). If you're on Windows,
- check out the unofficial `compiled Windows version`_.
-* If you're using MySQL, you'll need MySQLdb_.
+* If you're using PostgreSQL, you'll need the psycopg_ package. Django supports
+ both version 1 and 2. (When you configure Django's database layer, specify
+ either ``postgresql`` [for version 1] or ``postgresql_psycopg2`` [for version 2].)
+
+ If you're on Windows, check out the unofficial `compiled Windows version`_.
+
+* If you're using MySQL, you'll need MySQLdb_, version 1.2.1p2 or higher.
+ You will also want to read the database-specific notes for the `MySQL backend`_.
+
* If you're using SQLite, you'll need pysqlite_. Use version 2.0.3 or higher.
.. _PostgreSQL: http://www.postgresql.org/
.. _MySQL: http://www.mysql.com/
.. _Django's ticket system: http://code.djangoproject.com/report/1
-.. _psycopg: http://initd.org/projects/psycopg1
+.. _psycopg: http://initd.org/tracker/psycopg
.. _compiled Windows version: http://stickpeople.com/projects/python/win-psycopg/
.. _MySQLdb: http://sourceforge.net/projects/mysql-python
.. _SQLite: http://www.sqlite.org/
.. _pysqlite: http://initd.org/tracker/pysqlite
+.. _MySQL backend: ../databases/
+
+Remove any old versions of Django
+=================================
+
+If you are upgrading your installation of Django from a previous version,
+you will need to uninstall the old Django version before installing the
+new version.
+
+If you installed Django using ``setup.py install``, uninstalling
+is as simple as deleting the ``django`` directory from your Python
+``site-packages``.
+
+If you installed Django from a Python Egg, remove the Django ``.egg`` file,
+and remove the reference to the egg in the file named ``easy-install.pth``.
+This file should also be located in your ``site-packages`` directory.
+
+.. admonition:: Where are my ``site-packages`` stored?
+
+ The location of the ``site-packages`` directory depends on the operating
+ system, and the location in which Python was installed. However, the
+ following locations are common:
+
+ * If you're using Linux: ``/usr/lib/python2.X/site-packages``
+
+ * If you're using Windows: ``C:\Python2.X\lib\site-packages``
+
+ * If you're using MacOSX: ``/Library/Python2.X/site-packages`` or
+ ``/Library/Frameworks/Python.framework/Versions/2.X/lib/python2.X/site-packages/``
+ (in later releases).
Install the Django code
=======================
@@ -77,22 +112,23 @@ It's easy either way.
Installing the official version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-1. Download Django-0.95.tar.gz from our `download page`_.
-2. ``tar xzvf Django-0.95.tar.gz``
-3. ``cd Django-0.95``
-4. ``sudo python setup.py install``
+ 1. Check the `distribution specific notes`_ to see if your
+ platform/distribution provides official Django packages/installers.
+ Distribution-provided packages will typically allow for automatic
+ installation of dependancies and easy upgrade paths.
+
+ 2. Download the latest release from our `download page`_.
+
+ 3. Untar the downloaded file (e.g. ``tar xzvf Django-NNN.tar.gz``).
+
+ 4. Change into the downloaded directory (e.g. ``cd Django-NNN``).
-Note that the last command will automatically download and install setuptools_
-if you don't already have it installed. This requires a working Internet
-connection and may cause problems on Python 2.5. If you run into problems,
-try using our development version by following the instructions below. The
-development version no longer uses setuptools nor requires an Internet
-connection.
+ 5. Run ``sudo python setup.py install``.
The command will install Django in your Python installation's ``site-packages``
directory.
-.. _setuptools: http://peak.telecommunity.com/DevCenter/setuptools
+.. _distribution specific notes: ../distributions/
Installing the development version
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -113,14 +149,14 @@ latest bug fixes and improvements, follow these instructions:
svn co http://code.djangoproject.com/svn/django/trunk/django c:\Python24\lib\site-packages\django
-4. Copy the file ``django_src/django/bin/django-admin.py`` to somewhere on your
+3. Copy the file ``django_src/django/bin/django-admin.py`` to somewhere on your
system path, such as ``/usr/local/bin`` (Unix) or ``C:\Python24\Scripts``
(Windows). This step simply lets you type ``django-admin.py`` from within
any directory, rather than having to qualify the command with the full path
to the file.
You *don't* have to run ``python setup.py install``, because that command
-takes care of steps 3 and 4 for you.
+takes care of steps 2 and 3 for you.
When you want to update your copy of the Django source code, just run the
command ``svn update`` from within the ``django`` directory. When you do this,
diff --git a/docs/legacy_databases.txt b/docs/legacy_databases.txt
index 66cb1a2ef4..ca3927e52f 100644
--- a/docs/legacy_databases.txt
+++ b/docs/legacy_databases.txt
@@ -9,7 +9,7 @@ utilities to automate as much of this process as possible.
This document assumes you know the Django basics, as covered in the
`official tutorial`_.
-.. _official tutorial: http://www.djangoproject.com/documentation/tutorial1/
+.. _official tutorial: ../tutorial01/
Give Django your database parameters
====================================
@@ -22,18 +22,16 @@ what the name of the database is. Do that by editing these settings in your
* `DATABASE_ENGINE`_
* `DATABASE_USER`_
* `DATABASE_PASSWORD`_
- * `DATABASE_NAME`_
* `DATABASE_HOST`_
* `DATABASE_PORT`_
-.. _settings file: http://www.djangoproject.com/documentation/settings/
-.. _DATABASE_NAME: http://www.djangoproject.com/documentation/settings/#database-name
-.. _DATABASE_ENGINE: http://www.djangoproject.com/documentation/settings/#database-engine
-.. _DATABASE_USER: http://www.djangoproject.com/documentation/settings/#database-user
-.. _DATABASE_PASSWORD: http://www.djangoproject.com/documentation/settings/#database-password
-.. _DATABASE_NAME: http://www.djangoproject.com/documentation/settings/#database-name
-.. _DATABASE_HOST: http://www.djangoproject.com/documentation/settings/#database-host
-.. _DATABASE_PORT: http://www.djangoproject.com/documentation/settings/#database-port
+.. _settings file: ../settings/
+.. _DATABASE_NAME: ../settings/#database-name
+.. _DATABASE_ENGINE: ../settings/#database-engine
+.. _DATABASE_USER: ../settings/#database-user
+.. _DATABASE_PASSWORD: ../settings/#database-password
+.. _DATABASE_HOST: ../settings/#database-host
+.. _DATABASE_PORT: ../settings/#database-port
Auto-generate the models
========================
@@ -41,11 +39,11 @@ Auto-generate the models
Django comes with a utility that can create models by introspecting an existing
database. You can view the output by running this command::
- django-admin.py inspectdb --settings=path.to.settings
+ python manage.py inspectdb
Save this as a file by using standard Unix output redirection::
- django-admin.py inspectdb --settings=path.to.settings > models.py
+ python manage.py inspectdb > models.py
This feature is meant as a shortcut, not as definitive model generation. See
the `django-admin.py documentation`_ for more information.
@@ -54,7 +52,7 @@ Once you've cleaned up your models, name the file ``models.py`` and put it in
the Python package that holds your app. Then add the app to your
``INSTALLED_APPS`` setting.
-.. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
+.. _django-admin.py documentation: ../django-admin/
Install the core Django tables
==============================
@@ -62,7 +60,7 @@ Install the core Django tables
Next, run the ``manage.py syncdb`` command to install any extra needed database
records such as admin permissions and content types::
- django-admin.py init --settings=path.to.settings
+ python manage.py syncdb
See whether it worked
=====================
diff --git a/docs/man/django-admin.1 b/docs/man/django-admin.1
new file mode 100644
index 0000000000..fec5053ccb
--- /dev/null
+++ b/docs/man/django-admin.1
@@ -0,0 +1,162 @@
+.TH "django-admin.py" "1" "June 2007" "Django Project" ""
+.SH "NAME"
+django\-admin.py \- Utility script for the Django web framework
+.SH "SYNOPSIS"
+.B django\-admin.py
+.I <action>
+.B [options]
+.sp
+.SH "DESCRIPTION"
+This utility script provides commands for creation and maintenance of Django
+projects and apps.
+.sp
+With the exception of
+.BI startproject,
+all commands listed below can also be performed with the
+.BI manage.py
+script found at the top level of each Django project directory.
+.sp
+.SH "ACTIONS"
+.TP
+.BI "adminindex [" "appname ..." "]"
+Prints the admin\-index template snippet for the given app name(s).
+.TP
+.BI "createcachetable [" "tablename" "]"
+Creates the table needed to use the SQL cache backend
+.TP
+.B dbshell
+Runs the command\-line client for the current
+.BI DATABASE_ENGINE.
+.TP
+.B diffsettings
+Displays differences between the current
+.B settings.py
+and Django's default settings. Settings that don't appear in the defaults are
+followed by "###".
+.TP
+.B inspectdb
+Introspects the database tables in the database specified in settings.py and outputs a Django
+model module.
+.TP
+.BI "install [" "appname ..." "]"
+Executes
+.B sqlall
+for the given app(s) in the current database.
+.TP
+.BI "reset [" "appname ..." "]"
+Executes
+.B sqlreset
+for the given app(s) in the current database.
+.TP
+.BI "runfcgi [" "KEY=val" "] [" "KEY=val" "] " "..."
+Runs this project as a FastCGI application. Requires flup. Use
+.B runfcgi help
+for help on the KEY=val pairs.
+.TP
+.BI "runserver [" "\-\-noreload" "] [" "\-\-adminmedia=ADMIN_MEDIA_PATH" "] [" "port|ipaddr:port" "]"
+Starts a lightweight Web server for development.
+.TP
+.BI "shell [" "\-\-plain" "]"
+Runs a Python interactive interpreter. Tries to use IPython, if it's available.
+The
+.BI \-\-plain
+option forces the use of the standard Python interpreter even when IPython is
+installed.
+.TP
+.BI "sql [" "appname ..." "]"
+Prints the CREATE TABLE SQL statements for the given app name(s).
+.TP
+.BI "sqlall [" "appname ..." "]"
+Prints the CREATE TABLE, initial\-data and CREATE INDEX SQL statements for the
+given model module name(s).
+.TP
+.BI "sqlclear [" "appname ..." "]"
+Prints the DROP TABLE SQL statements for the given app name(s).
+.TP
+.BI "sqlindexes [" "appname ..." "]"
+Prints the CREATE INDEX SQL statements for the given model module name(s).
+.TP
+.BI "sqlinitialdata [" "appname ..." "]"
+Prints the initial INSERT SQL statements for the given app name(s).
+.TP
+.BI "sqlreset [" "appname ..." "]"
+Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app
+name(s).
+.TP
+.BI "sqlsequencereset [" "appname ..." "]"
+Prints the SQL statements for resetting PostgreSQL sequences for the
+given app name(s).
+.TP
+.BI "startapp [" "appname" "]"
+Creates a Django app directory structure for the given app name in
+the current directory.
+.TP
+.BI "startproject [" "projectname" "]"
+Creates a Django project directory structure for the given project name
+in the current directory.
+.TP
+.BI syncdb
+Creates the database tables for all apps in INSTALLED_APPS whose tables
+haven't already been created.
+.TP
+.BI "test [" "\-\-verbosity" "] [" "appname ..." "]"
+Runs the test suite for the specified applications, or the entire project if
+no apps are specified
+.TP
+.BI validate
+Validates all installed models.
+.SH "OPTIONS"
+.TP
+.I \-\-version
+Show program's version number and exit.
+.TP
+.I \-h, \-\-help
+Show this help message and exit.
+.TP
+.I \-\-settings=SETTINGS
+Python path to settings module, e.g. "myproject.settings.main". If
+this isn't provided, the DJANGO_SETTINGS_MODULE environment variable
+will be used.
+.TP
+.I \-\-pythonpath=PYTHONPATH
+Lets you manually add a directory the Python path,
+e.g. "/home/djangoprojects/myproject".
+.TP
+.I \-\-plain
+Use plain Python, not IPython, for the "shell" command.
+.TP
+.I \-\-noinput
+Do not prompt the user for input.
+.TP
+.I \-\-noreload
+Disable the development server's auto\-reloader.
+.TP
+.I \-\-verbosity=VERBOSITY
+Verbosity level: 0=minimal output, 1=normal output, 2=all output.
+.TP
+.I \-\-adminmedia=ADMIN_MEDIA_PATH
+Specifies the directory from which to serve admin media when using the development server.
+
+.SH "ENVIRONMENT"
+.TP
+.I DJANGO_SETTINGS_MODULE
+In the absence of the
+.BI \-\-settings
+option, this environment variable defines the settings module to be read.
+It should be in Python-import form, e.g. "myproject.settings".
+
+.SH "SEE ALSO"
+Full descriptions of all these options, with examples, as well as documentation
+for the rest of the Django framework, can be found on the Django site:
+.sp
+.I http://www.djangoproject.com/documentation/
+.sp
+or in the distributed documentation.
+.SH "AUTHORS/CREDITS"
+Originally developed at World Online in Lawrence, Kansas, USA. Refer to the
+AUTHORS file in the Django distribution for contributors.
+.sp
+.SH "LICENSE"
+New BSD license. For the full license text refer to the LICENSE file in the
+Django distribution.
+
diff --git a/docs/middleware.txt b/docs/middleware.txt
index efc4d89569..0d533443d3 100644
--- a/docs/middleware.txt
+++ b/docs/middleware.txt
@@ -47,7 +47,7 @@ Enables site-wide cache. If this is enabled, each Django-powered page will be
cached for as long as the ``CACHE_MIDDLEWARE_SECONDS`` setting defines. See
the `cache documentation`_.
-.. _`cache documentation`: http://www.djangoproject.com/documentation/cache/#the-per-site-cache
+.. _`cache documentation`: ../cache/#the-per-site-cache
django.middleware.common.CommonMiddleware
-----------------------------------------
@@ -104,11 +104,10 @@ Also removes the content from any response to a HEAD request and sets the
django.middleware.http.SetRemoteAddrFromForwardedFor
----------------------------------------------------
-**New in Django development version**
-
-Sets ``request['REMOTE_ADDR']`` based on ``request.['HTTP_X_FORWARDED_FOR']``,
-if the latter is set. This is useful if you're sitting behind a reverse proxy
-that causes each request's ``REMOTE_ADDR`` to be set to ``127.0.0.1``.
+Sets ``request.META['REMOTE_ADDR']`` based on
+``request.META['HTTP_X_FORWARDED_FOR']``, if the latter is set. This is useful
+if you're sitting behind a reverse proxy that causes each request's
+``REMOTE_ADDR`` to be set to ``127.0.0.1``.
**Important note:** This does NOT validate ``HTTP_X_FORWARDED_FOR``. If you're
not behind a reverse proxy that sets ``HTTP_X_FORWARDED_FOR`` automatically, do
@@ -122,7 +121,7 @@ django.contrib.sessions.middleware.SessionMiddleware
Enables session support. See the `session documentation`_.
-.. _`session documentation`: http://www.djangoproject.com/documentation/sessions/
+.. _`session documentation`: ../sessions/
django.contrib.auth.middleware.AuthenticationMiddleware
-------------------------------------------------------
@@ -130,7 +129,7 @@ django.contrib.auth.middleware.AuthenticationMiddleware
Adds the ``user`` attribute, representing the currently-logged-in user, to
every incoming ``HttpRequest`` object. See `Authentication in Web requests`_.
-.. _Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
+.. _Authentication in Web requests: ../authentication/#authentication-in-web-requests
django.middleware.transaction.TransactionMiddleware
---------------------------------------------------
@@ -146,7 +145,7 @@ the same transaction control as the view functions.
See the `transaction management documentation`_.
-.. _`transaction management documentation`: http://www.djangoproject.com/documentation/transactions/
+.. _`transaction management documentation`: ../transactions/
Writing your own middleware
===========================
diff --git a/docs/model-api.txt b/docs/model-api.txt
index 1aa8c811f4..09440f2b56 100644
--- a/docs/model-api.txt
+++ b/docs/model-api.txt
@@ -21,7 +21,7 @@ A companion to this document is the `official repository of model examples`_.
(In the Django source distribution, these examples are in the
``tests/modeltests`` directory.)
-.. _Database API reference: http://www.djangoproject.com/documentation/db_api/
+.. _Database API reference: ../db-api/
.. _official repository of model examples: http://www.djangoproject.com/documentation/models/
Quick example
@@ -57,7 +57,7 @@ Some technical notes:
syntax, but it's worth noting Django uses SQL tailored to the database
backend specified in your `settings file`_.
-.. _settings file: http://www.djangoproject.com/documentation/settings/
+.. _settings file: ../settings/
Fields
======
@@ -94,7 +94,7 @@ Django places only two restrictions on model field names:
the way Django's query lookup syntax works. For example::
class Example(models.Model):
- foo__bar = models.IntegerField() 'foo__bar' has two underscores!
+ foo__bar = models.IntegerField() # 'foo__bar' has two underscores!
These limitations can be worked around, though, because your field name doesn't
necessarily have to match your database column name. See `db_column`_ below.
@@ -184,6 +184,35 @@ A date and time field. Takes the same extra options as ``DateField``.
The admin represents this as two ``<input type="text">`` fields, with
JavaScript shortcuts.
+``DecimalField``
+~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+A fixed-precision decimal number, represented in Python by a ``Decimal`` instance.
+Has two **required** arguments:
+
+ ====================== ===================================================
+ Argument Description
+ ====================== ===================================================
+ ``max_digits`` The maximum number of digits allowed in the number.
+
+ ``decimal_places`` The number of decimal places to store with the
+ number.
+ ====================== ===================================================
+
+For example, to store numbers up to 999 with a resolution of 2 decimal places,
+you'd use::
+
+ models.DecimalField(..., max_digits=5, decimal_places=2)
+
+And to store numbers up to approximately one billion with a resolution of 10
+decimal places::
+
+ models.DecimalField(..., max_digits=19, decimal_places=10)
+
+The admin represents this as an ``<input type="text">`` (a single-line input).
+
``EmailField``
~~~~~~~~~~~~~~
@@ -194,14 +223,23 @@ This doesn't accept ``maxlength``; its ``maxlength`` is automatically set to
``FileField``
~~~~~~~~~~~~~
-A file-upload field.
+A file-upload field. Has one **required** argument:
+
+ ====================== ===================================================
+ Argument Description
+ ====================== ===================================================
+ ``upload_to`` A local filesystem path that will be appended to
+ your ``MEDIA_ROOT`` setting to determine the
+ output of the ``get_<fieldname>_url()`` helper
+ function.
+ ====================== ===================================================
-Has an extra required argument, ``upload_to``, a local filesystem path to
-which files should be upload. This path may contain `strftime formatting`_,
-which will be replaced by the date/time of the file upload (so that
-uploaded files don't fill up the given directory).
+This path may contain `strftime formatting`_, which will be replaced by the
+date/time of the file upload (so that uploaded files don't fill up the given
+directory).
-The admin represents this as an ``<input type="file">`` (a file-upload widget).
+The admin represents this field as an ``<input type="file">`` (a file-upload
+widget).
Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few
steps:
@@ -231,6 +269,13 @@ For example, say your ``MEDIA_ROOT`` is set to ``'/home/media'``, and
upload a file on Jan. 15, 2007, it will be saved in the directory
``/home/media/photos/2007/01/15``.
+If you want to retrieve the upload file's on-disk filename, or a URL that
+refers to that file, or the file's size, you can use the
+``get_FOO_filename()``, ``get_FOO_url()`` and ``get_FOO_size()`` methods.
+They are all documented here__.
+
+__ ../db-api/#get-foo-filename
+
Note that whenever you deal with uploaded files, you should pay close attention
to where you're uploading them and what type of files they are, to avoid
security holes. *Validate all uploaded files* so that you're sure the files are
@@ -246,7 +291,7 @@ visiting its URL on your site. Don't allow that.
A field whose choices are limited to the filenames in a certain directory
on the filesystem. Has three special arguments, of which the first is
-required:
+**required**:
====================== ===================================================
Argument Description
@@ -281,28 +326,16 @@ because the ``match`` applies to the base filename (``foo.gif`` and
``FloatField``
~~~~~~~~~~~~~~
-A floating-point number. Has two **required** arguments:
+**Changed in Django development version**
- ====================== ===================================================
- Argument Description
- ====================== ===================================================
- ``max_digits`` The maximum number of digits allowed in the number.
-
- ``decimal_places`` The number of decimal places to store with the
- number.
- ====================== ===================================================
+A floating-point number represented in Python by a ``float`` instance.
-For example, to store numbers up to 999 with a resolution of 2 decimal places,
-you'd use::
-
- models.FloatField(..., max_digits=5, decimal_places=2)
-
-And to store numbers up to approximately one billion with a resolution of 10
-decimal places::
+The admin represents this as an ``<input type="text">`` (a single-line input).
- models.FloatField(..., max_digits=19, decimal_places=10)
+**NOTE:** The semantics of ``FloatField`` have changed in the Django
+development version. See the `Django 0.96 documentation`_ for the old behavior.
-The admin represents this as an ``<input type="text">`` (a single-line input).
+.. _Django 0.96 documentation: http://www.djangoproject.com/documentation/0.96/model-api/#floatfield
``ImageField``
~~~~~~~~~~~~~~
@@ -312,9 +345,14 @@ image. Has two extra optional arguments, ``height_field`` and
``width_field``, which, if set, will be auto-populated with the height and
width of the image each time a model instance is saved.
+In addition to the special ``get_FOO_*`` methods that are available for
+``FileField``, an ``ImageField`` also has ``get_FOO_height()`` and
+``get_FOO_width()`` methods. These are documented elsewhere_.
+
Requires the `Python Imaging Library`_.
.. _Python Imaging Library: http://www.pythonware.com/products/pil/
+.. _elsewhere: ../db-api/#get-foo-height-and-get-foo-width
``IntegerField``
~~~~~~~~~~~~~~~~
@@ -362,9 +400,8 @@ Like a ``PositiveIntegerField``, but only allows values under a certain
containing only letters, numbers, underscores or hyphens. They're generally
used in URLs.
-In the Django development version, you can specify ``maxlength``. If
-``maxlength`` is not specified, Django will use a default length of 50. In
-previous Django versions, there's no way to override the length of 50.
+Like a CharField, you can specify ``maxlength``. If ``maxlength`` is
+not specified, Django will use a default length of 50.
Implies ``db_index=True``.
@@ -410,6 +447,11 @@ and doesn't give a 404 response).
The admin represents this as an ``<input type="text">`` (a single-line input).
+``URLField`` takes an optional argument, ``maxlength``, the maximum length (in
+characters) of the field. The maxlength is enforced at the database level and
+in Django's validation. If you don't specify ``maxlength``, a default of 200
+is used.
+
``USStateField``
~~~~~~~~~~~~~~~~
@@ -438,8 +480,10 @@ If ``True``, Django will store empty values as ``NULL`` in the database.
Default is ``False``.
Note that empty string values will always get stored as empty strings, not
-as ``NULL`` -- so use ``null=True`` for non-string fields such as integers,
-booleans and dates.
+as ``NULL``. Only use ``null=True`` for non-string fields such as integers,
+booleans and dates. For both types of fields, you will also need to set
+``blank=True`` if you wish to permit empty values in forms, as the ``null``
+parameter only affects database storage (see blank_, below).
Avoid using ``null`` on string-based fields such as ``CharField`` and
``TextField`` unless you have an excellent reason. If a string-based field
@@ -451,7 +495,7 @@ string, not ``NULL``.
``blank``
~~~~~~~~~
-If ``True``, the field is allowed to be blank.
+If ``True``, the field is allowed to be blank. Default is ``False``.
Note that this is different than ``null``. ``null`` is purely
database-related, whereas ``blank`` is validation-related. If a field has
@@ -498,6 +542,12 @@ or outside your model class altogether::
class Foo(models.Model):
gender = models.CharField(maxlength=1, choices=GENDER_CHOICES)
+For each model field that has ``choices`` set, Django will add a method to
+retrieve the human-readable name for the field's current value. See
+`get_FOO_display`_ in the database API documentation.
+
+.. _get_FOO_display: ../db-api/#get-foo-display
+
Finally, note that choices can be any iterable object -- not necessarily a
list or tuple. This lets you construct choices dynamically. But if you find
yourself hacking ``choices`` to be dynamic, you're probably better off using
@@ -621,7 +671,7 @@ that takes the parameters ``field_data, all_data`` and raises
Django comes with quite a few validators. They're in ``django.core.validators``.
-.. _validator docs: http://www.djangoproject.com/documentation/forms/#validators
+.. _validator docs: ../forms/#validators
Verbose field names
-------------------
@@ -729,10 +779,10 @@ relationship should work. All are optional:
``limit_choices_to`` A dictionary of lookup arguments and values (see
the `Database API reference`_) that limit the
available admin choices for this object. Use this
- with ``models.LazyDate`` to limit choices of objects
- by date. For example::
+ with functions from the Python ``datetime`` module
+ to limit choices of objects by date. For example::
- limit_choices_to = {'pub_date__lte': models.LazyDate()}
+ limit_choices_to = {'pub_date__lte': datetime.now}
only allows the choice of related objects with a
``pub_date`` before the current date/time to be
@@ -787,8 +837,8 @@ relationship should work. All are optional:
the related object.
======================= ============================================================
-.. _`Database API reference`: http://www.djangoproject.com/documentation/db_api/
-.. _related objects documentation: http://www.djangoproject.com/documentation/db_api/#related-objects
+.. _`Database API reference`: ../db-api/
+.. _related objects documentation: ../db-api/#related-objects
Many-to-many relationships
~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -875,6 +925,10 @@ the relationship should work. All are optional:
relationship, allowing ``ManyToMany`` relationships to be
non-symmetrical.
+ ``db_table`` The name of the table to create for storing the many-to-many
+ data. If this is not provided, Django will assume a default
+ name based upon the names of the two tables being joined.
+
======================= ============================================================
One-to-one relationships
@@ -954,7 +1008,7 @@ Example::
See the `docs for latest()`_ for more.
-.. _docs for latest(): http://www.djangoproject.com/documentation/db_api/#latest-field-name-none
+.. _docs for latest(): ../db-api/#latest-field-name-none
``order_with_respect_to``
-------------------------
@@ -1206,6 +1260,10 @@ screen via ``<script src="">`` tags. This can be used to tweak a given type of
admin page in JavaScript or to provide "quick links" to fill in default values
for certain fields.
+If you use relative URLs -- URLs that don't start with ``http://`` or ``/`` --
+then the admin site will automatically prefix these links with
+``settings.ADMIN_MEDIA_PREFIX``.
+
``list_display``
----------------
@@ -1268,15 +1326,53 @@ A few special cases to note about ``list_display``:
return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
colored_name.allow_tags = True
+ * If the string given is a method of the model that returns True or False
+ Django will display a pretty "on" or "off" icon if you give the method a
+ ``boolean`` attribute whose value is ``True``.
+
+ Here's a full example model::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=50)
+ birthday = models.DateField()
+
+ class Admin:
+ list_display = ('name', 'born_in_fifties')
+
+ def born_in_fifties(self):
+ return self.birthday.strftime('%Y')[:3] == 5
+ born_in_fifties.boolean = True
+
+
* The ``__str__()`` method is just as valid in ``list_display`` as any
other model method, so it's perfectly OK to do this::
list_display = ('__str__', 'some_other_field')
- * For any element of ``list_display`` that is not a field on the model, the
- change list page will not allow ordering by that column. This is because
- ordering is done at the database level, and Django has no way of knowing
- how to order the result of a custom method at the SQL level.
+ * Usually, elements of ``list_display`` that aren't actual database fields
+ can't be used in sorting (because Django does all the sorting at the
+ database level).
+
+ However, if an element of ``list_display`` represents a certain database
+ field, you can indicate this fact by setting the ``admin_order_field``
+ attribute of the item.
+
+ For example::
+
+ class Person(models.Model):
+ first_name = models.CharField(maxlength=50)
+ color_code = models.CharField(maxlength=6)
+
+ class Admin:
+ list_display = ('first_name', 'colored_first_name')
+
+ def colored_first_name(self):
+ return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
+ colored_first_name.allow_tags = True
+ colored_first_name.admin_order_field = 'first_name'
+
+ The above will tell Django to order by the ``first_name`` field when
+ trying to sort by ``colored_first_name`` in the admin.
``list_display_links``
----------------------
@@ -1346,7 +1442,7 @@ if one of the ``list_display`` fields is a ``ForeignKey``.
For more on ``select_related()``, see `the select_related() docs`_.
-.. _the select_related() docs: http://www.djangoproject.com/documentation/db_api/#select-related
+.. _the select_related() docs: ../db-api/#select-related
``ordering``
------------
@@ -1390,7 +1486,10 @@ This should be set to a list of field names that will be searched whenever
somebody submits a search query in that text box.
These fields should be some kind of text field, such as ``CharField`` or
-``TextField``.
+``TextField``. You can also perform a related lookup on a ``ForeignKey`` with
+the lookup API "follow" notation::
+
+ search_fields = ['foreign_key__related_fieldname']
When somebody does a search in the admin search box, Django splits the search
query into words and returns all objects that contain each of the words, case
@@ -1402,8 +1501,8 @@ user searches for ``john lennon``, Django will do the equivalent of this SQL
WHERE (first_name ILIKE '%john%' OR last_name ILIKE '%john%')
AND (first_name ILIKE '%lennon%' OR last_name ILIKE '%lennon%')
-**New in Django development version:** For faster and/or more restrictive
-searches, prefix the field name with an operator:
+For faster and/or more restrictive searches, prefix the field name
+with an operator:
``^``
Matches the beginning of the field. For example, if ``search_fields`` is
@@ -1448,7 +1547,7 @@ The way ``Manager`` classes work is documented in the `Retrieving objects`_
section of the database API docs, but this section specifically touches on
model options that customize ``Manager`` behavior.
-.. _Retrieving objects: http://www.djangoproject.com/documentation/db_api/#retrieving-objects
+.. _Retrieving objects: ../db-api/#retrieving-objects
Manager names
-------------
@@ -1696,11 +1795,58 @@ But this template code is good::
<a href="{{ object.get_absolute_url }}">{{ object.name }}</a>
-(Yes, we know ``get_absolute_url()`` couples URLs to models, which violates the
-DRY principle, because URLs are defined both in a URLconf and in the model.
-This is a rare case in which we've intentionally violated that principle for
-the sake of convenience. With that said, we're working on an even cleaner way
-of specifying URLs in a more DRY fashion.)
+.. note::
+ The string you return from ``get_absolute_url()`` must contain only ASCII
+ characters (required by the URI spec, `RFC 2396`_) that have been
+ URL-encoded, if necessary. Code and templates using ``get_absolute_url()``
+ should be able to use the result directly without needing to do any
+ further processing.
+
+.. _RFC 2396: http://www.ietf.org/rfc/rfc2396.txt
+
+The ``permalink`` decorator
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The problem with the way we wrote ``get_absolute_url()`` above is that it
+slightly violates the DRY principle: the URL for this object is defined both
+in the URLConf file and in the model.
+
+You can further decouple your models from the URLconf using the ``permalink``
+decorator. This decorator is passed the view function, a list of positional
+parameters and (optionally) a dictionary of named parameters. Django then
+works out the correct full URL path using the URLconf, substituting the
+parameters you have given into the URL. For example, if your URLconf
+contained a line such as::
+
+ (r'^/people/(\d+)/$', 'people.views.details'),
+
+...your model could have a ``get_absolute_url`` method that looked like this::
+
+ from django.db.models import permalink
+
+ def get_absolute_url(self):
+ return ('people.views.details', [str(self.id)])
+ get_absolute_url = permalink(get_absolute_url)
+
+Similarly, if you had a URLconf entry that looked like::
+
+ (r'/archive/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/$', archive_view)
+
+...you could reference this using ``permalink()`` as follows::
+
+ def get_absolute_url(self):
+ return ('archive_view', (), {
+ 'year': self.created.year,
+ 'month': self.created.month,
+ 'day': self.created.day})
+ get_absolute_url = permalink(get_absolute_url)
+
+Notice that we specify an empty sequence for the second argument in this case,
+because we only want to pass keyword arguments, not named arguments.
+
+In this way, you're tying the model's absolute URL to the view that is used
+to display it, without repeating the URL information anywhere. You can still
+use the ``get_absolute_url`` method in templates, as before.
Executing custom SQL
--------------------
@@ -1719,21 +1865,23 @@ rows. Example::
row = cursor.fetchone()
return row
-``connection`` and ``cursor`` simply use the standard `Python DB-API`_. If
-you're not familiar with the Python DB-API, note that the SQL statement in
-``cursor.execute()`` uses placeholders, ``"%s"``, rather than adding parameters
-directly within the SQL. If you use this technique, the underlying database
-library will automatically add quotes and escaping to your parameter(s) as
-necessary. (Also note that Django expects the ``"%s"`` placeholder, *not* the
-``"?"`` placeholder, which is used by the SQLite Python bindings. This is for
-the sake of consistency and sanity.)
+``connection`` and ``cursor`` mostly implement the standard `Python DB-API`_
+(except when it comes to `transaction handling`_). If you're not familiar with
+the Python DB-API, note that the SQL statement in ``cursor.execute()`` uses
+placeholders, ``"%s"``, rather than adding parameters directly within the SQL.
+If you use this technique, the underlying database library will automatically
+add quotes and escaping to your parameter(s) as necessary. (Also note that
+Django expects the ``"%s"`` placeholder, *not* the ``"?"`` placeholder, which is
+used by the SQLite Python bindings. This is for the sake of consistency and
+sanity.)
A final note: If all you want to do is a custom ``WHERE`` clause, you can just
just the ``where``, ``tables`` and ``params`` arguments to the standard lookup
API. See `Other lookup options`_.
.. _Python DB-API: http://www.python.org/peps/pep-0249.html
-.. _Other lookup options: http://www.djangoproject.com/documentation/db_api/#extra-params-select-where-tables
+.. _Other lookup options: ../db-api/#extra-params-select-where-tables
+.. _transaction handling: ../transactions/
Overriding default model methods
--------------------------------
@@ -1766,7 +1914,7 @@ You can also prevent saving::
else:
super(Blog, self).save() # Call the "real" save() method.
-.. _database API docs: http://www.djangoproject.com/documentation/db_api/
+.. _database API docs: ../db-api/
Models across files
===================
@@ -1823,7 +1971,7 @@ Each SQL file, if given, is expected to contain valid SQL. The SQL files are
piped directly into the database after all of the models' table-creation
statements have been executed.
-The SQL files are read by the ``sqlinitialdata``, ``sqlreset``, ``sqlall`` and
+The SQL files are read by the ``sqlcustom``, ``sqlreset``, ``sqlall`` and
``reset`` commands in ``manage.py``. Refer to the `manage.py documentation`_
for more information.
@@ -1832,7 +1980,7 @@ order in which they're executed. The only thing you can assume is that, by the
time your custom data files are executed, all the database tables already will
have been created.
-.. _`manage.py documentation`: http://www.djangoproject.com/documentation/django_admin/#sqlinitialdata-appname-appname
+.. _`manage.py documentation`: ../django-admin/#sqlcustom-appname-appname
Database-backend-specific SQL data
----------------------------------
diff --git a/docs/modpython.txt b/docs/modpython.txt
index 5177abf728..388a6168f3 100644
--- a/docs/modpython.txt
+++ b/docs/modpython.txt
@@ -13,14 +13,15 @@ other server arrangements.
Django requires Apache 2.x and mod_python 3.x, and you should use Apache's
`prefork MPM`_, as opposed to the `worker MPM`_.
-You may also be interested in `How to use Django with FastCGI`_.
+You may also be interested in `How to use Django with FastCGI, SCGI or AJP`_
+(which also covers SCGI and AJP).
.. _Apache: http://httpd.apache.org/
.. _mod_python: http://www.modpython.org/
.. _mod_perl: http://perl.apache.org/
.. _prefork MPM: http://httpd.apache.org/docs/2.2/mod/prefork.html
.. _worker MPM: http://httpd.apache.org/docs/2.2/mod/worker.html
-.. _How to use Django with FastCGI: http://www.djangoproject.com/documentation/fastcgi/
+.. _How to use Django with FastCGI, SCGI or AJP: ../fastcgi/
Basic configuration
===================
@@ -37,7 +38,8 @@ Then edit your ``httpd.conf`` file and add the following::
PythonDebug On
</Location>
-...and replace ``mysite.settings`` with the Python path to your settings file.
+...and replace ``mysite.settings`` with the Python import path to your Django
+project's settings file.
This tells Apache: "Use mod_python for any URL at or under '/mysite/', using the
Django mod_python handler." It passes the value of ``DJANGO_SETTINGS_MODULE``
@@ -49,9 +51,29 @@ whereas ``<Location>`` points at places in the URL structure of a Web site.
``<Directory>`` would be meaningless here.
Also, if you've manually altered your ``PYTHONPATH`` to put your Django project
-on it, you'll need to tell mod_python::
+on it, you'll need to tell mod_python:
- PythonPath "['/path/to/project'] + sys.path"
+.. parsed-literal::
+
+ <Location "/mysite/">
+ SetHandler python-program
+ PythonHandler django.core.handlers.modpython
+ SetEnv DJANGO_SETTINGS_MODULE mysite.settings
+ PythonDebug On
+ **PythonPath "['/path/to/project'] + sys.path"**
+ </Location>
+
+.. caution::
+
+ If you're using Windows, remember that the path will contain backslashes.
+ This string is passed through Python's string parser twice, so you need to
+ escape each backslash **twice**::
+
+ PythonPath "['c:\\\\path\\\\to\\\\project'] + sys.path"
+
+ Or, use raw strings::
+
+ PythonPath "[r'c:\\path\\to\\project'] + sys.path"
You can also add directives such as ``PythonAutoReload Off`` for performance.
See the `mod_python documentation`_ for a full list of options.
@@ -146,7 +168,7 @@ If, however, you have no option but to serve media files on the same Apache
``VirtualHost`` as Django, here's how you can turn off mod_python for a
particular part of the site::
- <Location "/media/">
+ <Location "/media">
SetHandler None
</Location>
@@ -163,7 +185,7 @@ the ``media`` subdirectory and any URL that ends with ``.jpg``, ``.gif`` or
SetEnv DJANGO_SETTINGS_MODULE mysite.settings
</Location>
- <Location "media">
+ <Location "/media">
SetHandler None
</Location>
@@ -197,6 +219,41 @@ Here are two recommended approaches:
2. Or, copy the admin media files so that they live within your Apache
document root.
+Using eggs with mod_python
+==========================
+
+If you installed Django from a Python egg_ or are using eggs in your Django
+project, some extra configuration is required. Create an extra file in your
+project (or somewhere else) that contains something like the following::
+
+ import os
+ os.environ['PYTHON_EGG_CACHE'] = '/some/directory'
+
+Here, ``/some/directory`` is a directory that the Apache webserver process can
+write to. It will be used as the location for any unpacking of code the eggs
+need to do.
+
+Then you have to tell mod_python to import this file before doing anything
+else. This is done using the PythonImport_ directive to mod_python. You need
+to ensure that you have specified the ``PythonInterpreter`` directive to
+mod_python as described above__ (you need to do this even if you aren't
+serving multiple installations in this case). Then add the ``PythonImport``
+line inside the ``Location`` or ``VirtualHost`` section. For example::
+
+ PythonInterpreter my_django
+ PythonImport /path/to/my/project/file.py my_django
+
+Note that you can use an absolute path here (or a normal dotted import path),
+as described in the `mod_python manual`_. We use an absolute path in the
+above example because if any Python path modifications are required to access
+your project, they will not have been done at the time the ``PythonImport``
+line is processed.
+
+.. _Egg: http://peak.telecommunity.com/DevCenter/PythonEggs
+.. _PythonImport: http://www.modpython.org/live/current/doc-html/dir-other-pimp.html
+.. _mod_python manual: PythonImport_
+__ `Multiple Django installations on the same Apache`_
+
Error handling
==============
@@ -242,3 +299,5 @@ as necessary.
.. _Expat Causing Apache Crash: http://www.dscpl.com.au/articles/modpython-006.html
.. _mod_python FAQ entry: http://modpython.org/FAQ/faqw.py?req=show&file=faq02.013.htp
.. _Getting mod_python Working: http://www.dscpl.com.au/articles/modpython-001.html
+
+
diff --git a/docs/newforms.txt b/docs/newforms.txt
index c4986eb45e..1511791a7d 100644
--- a/docs/newforms.txt
+++ b/docs/newforms.txt
@@ -2,34 +2,37 @@
The newforms library
====================
-``django.newforms`` is a new replacement for ``django.forms``, the old Django
-form/manipulator/validation framework. This document explains how to use this
-new form library.
+``django.newforms`` is Django's fantastic new form-handling library. It's a
+replacement for ``django.forms``, the old form/manipulator/validation
+framework. This document explains how to use this new library.
Migration plan
==============
-``django.newforms`` currently is only available in the Django development version
--- i.e., it's not available in the Django 0.95 release. For the next Django
-release, our plan is to do the following:
+``django.newforms`` is new in Django's 0.96 release, but, as it won't be new
+forever, we plan to rename it to ``django.forms`` in the future. The current
+``django.forms`` package will be available as ``django.oldforms`` until Django
+1.0, when we plan to remove it for good.
- * As of revision [4208], we've copied the current ``django.forms`` to
- ``django.oldforms``. This allows you to upgrade your code *now* rather
- than waiting for the backwards-incompatible change and rushing to fix
- your code after the fact. Just change your import statements like this::
+That has direct repercussions on the forward compatibility of your code. Please
+read the following migration plan and code accordingly:
+
+ * The old forms framework (the current ``django.forms``) has been copied to
+ ``django.oldforms``. Thus, you can start upgrading your code *now*,
+ rather than waiting for the future backwards-incompatible change, by
+ changing your import statements like this::
from django import forms # old
from django import oldforms as forms # new
- * At an undecided future date, we will move the current ``django.newforms``
- to ``django.forms``. This will be a backwards-incompatible change, and
- anybody who is still using the old version of ``django.forms`` at that
- time will need to change their import statements, as described in the
- previous bullet.
+ * In the next Django release (0.97), we will move the current
+ ``django.newforms`` to ``django.forms``. This will be a
+ backwards-incompatible change, and anybody who is still using the old
+ version of ``django.forms`` at that time will need to change their import
+ statements, as described in the previous bullet.
* We will remove ``django.oldforms`` in the release *after* the next Django
- release -- the release that comes after the release in which we're
- creating the new ``django.forms``.
+ release -- either 0.98 or 1.0, whichever comes first.
With this in mind, we recommend you use the following import statement when
using ``django.newforms``::
@@ -51,9 +54,10 @@ too messy. The choice is yours.
Overview
========
-As the ``django.forms`` ("manipulators") system before it, ``django.newforms``
-is intended to handle HTML form display, validation and redisplay. It's what
-you use if you want to perform server-side validation for an HTML form.
+As with the ``django.forms`` ("manipulators") system before it,
+``django.newforms`` is intended to handle HTML form display, data processing
+(validation) and redisplay. It's what you use if you want to perform
+server-side validation for an HTML form.
For example, if your Web site has a contact form that visitors can use to
send you e-mail, you'd use this library to implement the display of the HTML
@@ -72,6 +76,12 @@ The library deals with these concepts:
* **Form** -- A collection of fields that knows how to validate itself and
display itself as HTML.
+The library is decoupled from the other Django components, such as the database
+layer, views and templates. It relies only on Django settings, a couple of
+``django.utils`` helper functions and Django's internationalization hooks (but
+you're not required to be using internationalization features to use this
+library).
+
Form objects
============
@@ -79,8 +89,8 @@ The primary way of using the ``newforms`` library is to create a form object.
Do this by subclassing ``django.newforms.Form`` and specifying the form's
fields, in a declarative style that you'll be familiar with if you've used
Django database models. In this section, we'll iteratively develop a form
-object that you might to implement "contact me" functionality on your personal
-Web site.
+object that you might use to implement "contact me" functionality on your
+personal Web site.
Start with this basic ``Form`` subclass, which we'll call ``ContactForm``::
@@ -97,11 +107,224 @@ fields: ``subject``, ``message``, ``sender`` and ``cc_myself``. We'll explain
the different types of fields -- e.g., ``CharField`` and ``EmailField`` --
shortly.
+Creating ``Form`` instances
+---------------------------
+
+A ``Form`` instance is either **bound** or **unbound** to a set of data.
+
+ * If it's **bound** to a set of data, it's capable of validating that data
+ and rendering the form as HTML with the data displayed in the HTML.
+
+ * If it's **unbound**, it cannot do validation (because there's no data to
+ validate!), but it can still render the blank form as HTML.
+
+To create an unbound ``Form`` instance, simply instantiate the class::
+
+ >>> f = ContactForm()
+
+To bind data to a form, pass the data as a dictionary as the first parameter to
+your ``Form`` class constructor::
+
+ >>> data = {'subject': 'hello',
+ ... 'message': 'Hi there',
+ ... 'sender': 'foo@example.com',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+
+In this dictionary, the keys are the field names, which correspond to the
+attributes in your ``Form`` class. The values are the data you're trying
+to validate. These will usually be strings, but there's no requirement that
+they be strings; the type of data you pass depends on the ``Field``, as we'll
+see in a moment.
+
+If you need to distinguish between bound and unbound form instances at runtime,
+check the value of the form's ``is_bound`` attribute::
+
+ >>> f = ContactForm()
+ >>> f.is_bound
+ False
+ >>> f = ContactForm({'subject': 'hello'})
+ >>> f.is_bound
+ True
+
+Note that passing an empty dictionary creates a *bound* form with empty data::
+
+ >>> f = ContactForm({})
+ >>> f.is_bound
+ True
+
+If you have a bound ``Form`` instance and want to change the data somehow, or
+if you want to bind an unbound ``Form`` instance to some data, create another
+``Form`` instance. There is no way to change data in a ``Form`` instance. Once
+a ``Form`` instance has been created, you should consider its data immutable,
+whether it has data or not.
+
+Using forms to validate data
+----------------------------
+
+The primary task of a ``Form`` object is to validate data. With a bound
+``Form`` instance, call the ``is_valid()`` method to run validation and return
+a boolean designating whether the data was valid::
+
+ >>> data = {'subject': 'hello',
+ ... 'message': 'Hi there',
+ ... 'sender': 'foo@example.com',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+ >>> f.is_valid()
+ True
+
+Let's try with some invalid data. In this case, ``subject`` is blank (an error,
+because all fields are required by default) and ``sender`` is not a valid
+e-mail address::
+
+ >>> data = {'subject': '',
+ ... 'message': 'Hi there',
+ ... 'sender': 'invalid e-mail address',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+ >>> f.is_valid()
+ False
+
+Access the ``errors`` attribute to get a dictionary of error messages::
+
+ >>> f.errors
+ {'sender': [u'Enter a valid e-mail address.'], 'subject': [u'This field is required.']}
+
+In this dictionary, the keys are the field names, and the values are lists of
+Unicode strings representing the error messages. The error messages are stored
+in lists because a field can have multiple error messages.
+
+You can access ``errors`` without having to call ``is_valid()`` first. The
+form's data will be validated the first time either you call ``is_valid()`` or
+access ``errors``.
+
+The validation routines will only get called once, regardless of how many times
+you access ``errors`` or call ``is_valid()``. This means that if validation has
+side effects, those side effects will only be triggered once.
+
+Behavior of unbound forms
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It's meaningless to validate a form with no data, but, for the record, here's
+what happens with unbound forms::
+
+ >>> f = ContactForm()
+ >>> f.is_valid()
+ False
+ >>> f.errors
+ {}
+
+Accessing "clean" data
+----------------------
+
+Each ``Field`` in a ``Form`` class is responsible not only for validating data,
+but also for "cleaning" it -- normalizing it to a consistent format. This is a
+nice feature, because it allows data for a particular field to be input in
+a variety of ways, always resulting in consistent output.
+
+For example, ``DateField`` normalizes input into a Python ``datetime.date``
+object. Regardless of whether you pass it a string in the format
+``'1994-07-15'``, a ``datetime.date`` object or a number of other formats,
+``DateField`` will always normalize it to a ``datetime.date`` object as long as
+it's valid.
+
+Once you've created a ``Form`` instance with a set of data and validated it,
+you can access the clean data via the ``cleaned_data`` attribute of the ``Form``
+object::
+
+ >>> data = {'subject': 'hello',
+ ... 'message': 'Hi there',
+ ... 'sender': 'foo@example.com',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+ >>> f.is_valid()
+ True
+ >>> f.cleaned_data
+ {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
+
+Note that any text-based field -- such as ``CharField`` or ``EmailField`` --
+always cleans the input into a Unicode string. We'll cover the encoding
+implications later in this document.
+
+If your data does *not* validate, your ``Form`` instance will not have a
+``cleaned_data`` attribute::
+
+ >>> data = {'subject': '',
+ ... 'message': 'Hi there',
+ ... 'sender': 'invalid e-mail address',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+ >>> f.is_valid()
+ False
+ >>> f.cleaned_data
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
+
+``cleaned_data`` will always *only* contain a key for fields defined in the
+``Form``, even if you pass extra data when you define the ``Form``. In this
+example, we pass a bunch of extra fields to the ``ContactForm`` constructor,
+but ``cleaned_data`` contains only the form's fields::
+
+ >>> data = {'subject': 'hello',
+ ... 'message': 'Hi there',
+ ... 'sender': 'foo@example.com',
+ ... 'cc_myself': True,
+ ... 'extra_field_1': 'foo',
+ ... 'extra_field_2': 'bar',
+ ... 'extra_field_3': 'baz'}
+ >>> f = ContactForm(data)
+ >>> f.is_valid()
+ True
+ >>> f.cleaned_data # Doesn't contain extra_field_1, etc.
+ {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
+
+``cleaned_data`` will include a key and value for *all* fields defined in the
+``Form``, even if the data didn't include a value for fields that are not
+required. In this example, the data dictionary doesn't include a value for the
+``nick_name`` field, but ``cleaned_data`` includes it, with an empty value::
+
+ >>> class OptionalPersonForm(Form):
+ ... first_name = CharField()
+ ... last_name = CharField()
+ ... nick_name = CharField(required=False)
+ >>> data = {'first_name': u'John', 'last_name': u'Lennon'}
+ >>> f = OptionalPersonForm(data)
+ >>> f.is_valid()
+ True
+ >>> f.cleaned_data
+ {'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
+
+In this above example, the ``cleaned_data`` value for ``nick_name`` is set to an
+empty string, because ``nick_name`` is ``CharField``, and ``CharField``\s treat
+empty values as an empty string. Each field type knows what its "blank" value
+is -- e.g., for ``DateField``, it's ``None`` instead of the empty string. For
+full details on each field's behavior in this case, see the "Empty value" note
+for each field in the "Built-in ``Field`` classes" section below.
+
+You can write code to perform validation for particular form fields (based on
+their name) or for the form as a whole (considering combinations of various
+fields). More information about this is in the `Custom form and field
+validation`_ section, below.
+
+Behavior of unbound forms
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+It's meaningless to request "cleaned" data in a form with no data, but, for the
+record, here's what happens with unbound forms::
+
+ >>> f = ContactForm()
+ >>> f.cleaned_data
+ Traceback (most recent call last):
+ ...
+ AttributeError: 'ContactForm' object has no attribute 'cleaned_data'
+
Outputting forms as HTML
------------------------
-The first thing we can do with this is output it as HTML. To do so, instantiate
-it and ``print`` it::
+The second task of a ``Form`` object is to render itself as HTML. To do so,
+simply ``print`` it::
>>> f = ContactForm()
>>> print f
@@ -110,6 +333,23 @@ it and ``print`` it::
<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
+If the form is bound to data, the HTML output will include that data
+appropriately. For example, if a field is represented by an
+``<input type="text">``, the data will be in the ``value`` attribute. If a
+field is represented by an ``<input type="checkbox">``, then that HTML will
+include ``checked="checked"`` if appropriate::
+
+ >>> data = {'subject': 'hello',
+ ... 'message': 'Hi there',
+ ... 'sender': 'foo@example.com',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data)
+ >>> print f
+ <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
+ <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
+ <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
+ <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>
+
This default output is a two-column HTML table, with a ``<tr>`` for each field.
Notice the following:
@@ -121,13 +361,13 @@ Notice the following:
``EmailField`` are represented by an ``<input type="text">``.
``BooleanField`` is represented by an ``<input type="checkbox">``. Note
these are merely sensible defaults; you can specify which HTML to use for
- a given field by using ``widgets``, which we'll explain shortly.
+ a given field by using widgets, which we'll explain shortly.
* The HTML ``name`` for each tag is taken directly from its attribute name
in the ``ContactForm`` class.
* The text label for each field -- e.g. ``'Subject:'``, ``'Message:'`` and
- ``'CC myself:'`` is generated from the field name by converting all
+ ``'Cc myself:'`` is generated from the field name by converting all
underscores to spaces and upper-casing the first letter. Again, note
these are merely sensible defaults; you can also specify labels manually.
@@ -248,7 +488,7 @@ field::
If ``auto_id`` is set to a string containing the format character ``'%s'``,
then the form output will include ``<label>`` tags, and will generate ``id``
attributes based on the format string. For example, for a format string
-``'field_%s'``, a field named ``subject`` will get the ``id``
+``'field_%s'``, a field named ``subject`` will get the ``id`` value
``'field_subject'``. Continuing our example::
>>> f = ContactForm(auto_id='id_for_%s')
@@ -282,6 +522,1117 @@ example, in the ``ContactForm`` example, the fields are defined in the order
``subject``, ``message``, ``sender``, ``cc_myself``. To reorder the HTML
output, just change the order in which those fields are listed in the class.
+How errors are displayed
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you render a bound ``Form`` object, the act of rendering will automatically
+run the form's validation if it hasn't already happened, and the HTML output
+will include the validation errors as a ``<ul class="errorlist">`` near the
+field. The particular positioning of the error messages depends on the output
+method you're using::
+
+ >>> data = {'subject': '',
+ ... 'message': 'Hi there',
+ ... 'sender': 'invalid e-mail address',
+ ... 'cc_myself': True}
+ >>> f = ContactForm(data, auto_id=False)
+ >>> print f.as_table()
+ <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
+ <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
+ <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr>
+ <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
+ >>> print f.as_ul()
+ <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
+ <li>Message: <input type="text" name="message" value="Hi there" /></li>
+ <li><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li>
+ <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
+ >>> print f.as_p()
+ <p><ul class="errorlist"><li>This field is required.</li></ul></p>
+ <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
+ <p>Message: <input type="text" name="message" value="Hi there" /></p>
+ <p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p>
+ <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
+ <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
+
+More granular output
+~~~~~~~~~~~~~~~~~~~~
+
+The ``as_p()``, ``as_ul()`` and ``as_table()`` methods are simply shortcuts for
+lazy developers -- they're not the only way a form object can be displayed.
+
+To display the HTML for a single field in your form, use dictionary lookup
+syntax using the field's name as the key, and print the resulting object::
+
+ >>> f = ContactForm()
+ >>> print f['subject']
+ <input id="id_subject" type="text" name="subject" maxlength="100" />
+ >>> print f['message']
+ <input type="text" name="message" id="id_message" />
+ >>> print f['sender']
+ <input type="text" name="sender" id="id_sender" />
+ >>> print f['cc_myself']
+ <input type="checkbox" name="cc_myself" id="id_cc_myself" />
+
+Call ``str()`` or ``unicode()`` on the field to get its rendered HTML as a
+string or Unicode object, respectively::
+
+ >>> str(f['subject'])
+ '<input id="id_subject" type="text" name="subject" maxlength="100" />'
+ >>> unicode(f['subject'])
+ u'<input id="id_subject" type="text" name="subject" maxlength="100" />'
+
+The field-specific output honors the form object's ``auto_id`` setting::
+
+ >>> f = ContactForm(auto_id=False)
+ >>> print f['message']
+ <input type="text" name="message" />
+ >>> f = ContactForm(auto_id='id_%s')
+ >>> print f['message']
+ <input type="text" name="message" id="id_message" />
+
+For a field's list of errors, access the field's ``errors`` attribute. This
+is a list-like object that is displayed as an HTML ``<ul class="errorlist">``
+when printed::
+
+ >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
+ >>> f = ContactForm(data, auto_id=False)
+ >>> print f['message']
+ <input type="text" name="message" />
+ >>> f['message'].errors
+ [u'This field is required.']
+ >>> print f['message'].errors
+ <ul class="errorlist"><li>This field is required.</li></ul>
+ >>> f['subject'].errors
+ []
+ >>> print f['subject'].errors
+
+ >>> str(f['subject'].errors)
+ ''
+
+Using forms in views and templates
+----------------------------------
+
+Let's put this all together and use the ``ContactForm`` example in a Django
+view and template.
+
+Simple view example
+~~~~~~~~~~~~~~~~~~~
+
+This example view displays the contact form by default and validates/processes
+it if accessed via a POST request::
+
+ def contact(request):
+ if request.method == 'POST':
+ form = ContactForm(request.POST)
+ if form.is_valid():
+ # Do form processing here...
+ return HttpResponseRedirect('/url/on_success/')
+ else:
+ form = ContactForm()
+ return render_to_response('contact.html', {'form': form})
+
+Simple template example
+~~~~~~~~~~~~~~~~~~~~~~~
+
+The template in the above view example, ``contact.html``, is responsible for
+displaying the form as HTML. To do this, we can use the techniques outlined in
+the "Outputting forms as HTML" section above.
+
+The simplest way to display a form's HTML is to use the variable on its own,
+like this::
+
+ <form method="post">
+ <table>{{ form }}</table>
+ <input type="submit" />
+ </form>
+
+The above template code will display the form as an HTML table, using the
+``form.as_table()`` method explained previously. This works because Django's
+template system displays an object's ``__str__()`` value, and the ``Form``
+class' ``__str__()`` method calls its ``as_table()`` method.
+
+The following is equivalent but a bit more explicit::
+
+ <form method="post">
+ <table>{{ form.as_table }}</table>
+ <input type="submit" />
+ </form>
+
+``form.as_ul`` and ``form.as_p`` are also available, as you may expect.
+
+Note that in the above two examples, we included the ``<form>``, ``<table>``
+``<input type="submit" />``, ``</table>`` and ``</form>`` tags. The form
+convenience methods (``as_table()``, ``as_ul()`` and ``as_p()``) do not include
+that HTML.
+
+Complex template output
+~~~~~~~~~~~~~~~~~~~~~~~
+
+As we've stressed several times, the ``as_table()``, ``as_ul()`` and ``as_p()``
+methods are just shortcuts for the common case. You can also work with the
+individual fields for complete template control over the form's design.
+
+The easiest way is to iterate over the form's fields, with
+``{% for field in form %}``. For example::
+
+ <form method="post">
+ <dl>
+ {% for field in form %}
+ <dt>{{ field.label }}</dt>
+ <dd>{{ field }}</dd>
+ {% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
+ {% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}
+ {% endfor %}
+ </dl>
+ <input type="submit" />
+ </form>
+
+This iteration technique is useful if you want to apply the same HTML
+formatting to each field, or if you don't know the names of the form fields
+ahead of time. Note that the fields will be iterated over in the order in which
+they're defined in the ``Form`` class.
+
+Alternatively, you can arrange the form's fields explicitly, by name. Do that
+by accessing ``{{ form.fieldname }}``, where ``fieldname`` is the field's name.
+For example::
+
+ <form method="post">
+ <ul class="myformclass">
+ <li>{{ form.sender.label }} {{ form.sender }}</li>
+ <li class="helptext">{{ form.sender.help_text }}</li>
+ {% if form.sender.errors %}<ul class="errorlist">{{ form.sender.errors }}</ul>{% endif %}
+
+ <li>{{ form.subject.label }} {{ form.subject }}</li>
+ <li class="helptext">{{ form.subject.help_text }}</li>
+ {% if form.subject.errors %}<ul class="errorlist">{{ form.subject.errors }}</ul>{% endif %}
+
+ ...
+ </ul>
+ </form>
+
+Subclassing forms
+-----------------
+
+If you have multiple ``Form`` classes that share fields, you can use
+subclassing to remove redundancy.
+
+When you subclass a custom ``Form`` class, the resulting subclass will
+include all fields of the parent class(es), followed by the fields you define
+in the subclass.
+
+In this example, ``ContactFormWithPriority`` contains all the fields from
+``ContactForm``, plus an additional field, ``priority``. The ``ContactForm``
+fields are ordered first::
+
+ >>> class ContactFormWithPriority(ContactForm):
+ ... priority = forms.CharField()
+ >>> f = ContactFormWithPriority(auto_id=False)
+ >>> print f.as_ul()
+ <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
+ <li>Message: <input type="text" name="message" /></li>
+ <li>Sender: <input type="text" name="sender" /></li>
+ <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
+ <li>Priority: <input type="text" name="priority" /></li>
+
+It's possible to subclass multiple forms, treating forms as "mix-ins." In this
+example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
+(in that order), and its field list includes the fields from the parent
+classes::
+
+ >>> class PersonForm(Form):
+ ... first_name = CharField()
+ ... last_name = CharField()
+ >>> class InstrumentForm(Form):
+ ... instrument = CharField()
+ >>> class BeatleForm(PersonForm, InstrumentForm):
+ ... haircut_type = CharField()
+ >>> b = BeatleForm(auto_id=False)
+ >>> print b.as_ul()
+ <li>First name: <input type="text" name="first_name" /></li>
+ <li>Last name: <input type="text" name="last_name" /></li>
+ <li>Instrument: <input type="text" name="instrument" /></li>
+ <li>Haircut type: <input type="text" name="haircut_type" /></li>
+
+Fields
+======
+
+When you create a ``Form`` class, the most important part is defining the
+fields of the form. Each field has custom validation logic, along with a few
+other hooks.
+
+Although the primary way you'll use ``Field`` classes is in ``Form`` classes,
+you can also instantiate them and use them directly to get a better idea of
+how they work. Each ``Field`` instance has a ``clean()`` method, which takes
+a single argument and either raises a ``django.newforms.ValidationError``
+exception or returns the clean value::
+
+ >>> f = forms.EmailField()
+ >>> f.clean('foo@example.com')
+ u'foo@example.com'
+ >>> f.clean(u'foo@example.com')
+ u'foo@example.com'
+ >>> f.clean('invalid e-mail address')
+ Traceback (most recent call last):
+ ...
+ ValidationError: [u'Enter a valid e-mail address.']
+
+If you've used Django's old forms/validation framework, take care in noticing
+this ``ValidationError`` is different than the previous ``ValidationError``.
+This one lives at ``django.newforms.ValidationError`` rather than
+``django.core.validators.ValidationError``.
+
+Core field arguments
+--------------------
+
+Each ``Field`` class constructor takes at least these arguments. Some
+``Field`` classes take additional, field-specific arguments, but the following
+should *always* be accepted:
+
+``required``
+~~~~~~~~~~~~
+
+By default, each ``Field`` class assumes the value is required, so if you pass
+an empty value -- either ``None`` or the empty string (``""``) -- then
+``clean()`` will raise a ``ValidationError`` exception::
+
+ >>> f = forms.CharField()
+ >>> f.clean('foo')
+ u'foo'
+ >>> f.clean('')
+ Traceback (most recent call last):
+ ...
+ ValidationError: [u'This field is required.']
+ >>> f.clean(None)
+ Traceback (most recent call last):
+ ...
+ ValidationError: [u'This field is required.']
+ >>> f.clean(' ')
+ u' '
+ >>> f.clean(0)
+ u'0'
+ >>> f.clean(True)
+ u'True'
+ >>> f.clean(False)
+ u'False'
+
+To specify that a field is *not* required, pass ``required=False`` to the
+``Field`` constructor::
+
+ >>> f = forms.CharField(required=False)
+ >>> f.clean('foo')
+ u'foo'
+ >>> f.clean('')
+ u''
+ >>> f.clean(None)
+ u''
+ >>> f.clean(0)
+ u'0'
+ >>> f.clean(True)
+ u'True'
+ >>> f.clean(False)
+ u'False'
+
+If a ``Field`` has ``required=False`` and you pass ``clean()`` an empty value,
+then ``clean()`` will return a *normalized* empty value rather than raising
+``ValidationError``. For ``CharField``, this will be a Unicode empty string.
+For other ``Field`` classes, it might be ``None``. (This varies from field to
+field.)
+
+``label``
+~~~~~~~~~
+
+The ``label`` argument lets you specify the "human-friendly" label for this
+field. This is used when the ``Field`` is displayed in a ``Form``.
+
+As explained in "Outputting forms as HTML" above, the default label for a
+``Field`` is generated from the field name by converting all underscores to
+spaces and upper-casing the first letter. Specify ``label`` if that default
+behavior doesn't result in an adequate label.
+
+Here's a full example ``Form`` that implements ``label`` for two of its fields.
+We've specified ``auto_id=False`` to simplify the output::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField(label='Your name')
+ ... url = forms.URLField(label='Your Web site', required=False)
+ ... comment = forms.CharField()
+ >>> f = CommentForm(auto_id=False)
+ >>> print f
+ <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
+ <tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+
+``initial``
+~~~~~~~~~~~
+
+The ``initial`` argument lets you specify the initial value to use when
+rendering this ``Field`` in an unbound ``Form``.
+
+The use-case for this is when you want to display an "empty" form in which a
+field is initialized to a particular value. For example::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField(initial='Your name')
+ ... url = forms.URLField(initial='http://')
+ ... comment = forms.CharField()
+ >>> f = CommentForm(auto_id=False)
+ >>> print f
+ <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
+ <tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+
+You may be thinking, why not just pass a dictionary of the initial values as
+data when displaying the form? Well, if you do that, you'll trigger validation,
+and the HTML output will include any validation errors::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField()
+ ... url = forms.URLField()
+ ... comment = forms.CharField()
+ >>> default_data = {'name': 'Your name', 'url': 'http://'}
+ >>> f = CommentForm(default_data, auto_id=False)
+ >>> print f
+ <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
+ <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr>
+ <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
+
+This is why ``initial`` values are only displayed for unbound forms. For bound
+forms, the HTML output will use the bound data.
+
+Also note that ``initial`` values are *not* used as "fallback" data in
+validation if a particular field's value is not given. ``initial`` values are
+*only* intended for initial form display::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField(initial='Your name')
+ ... url = forms.URLField(initial='http://')
+ ... comment = forms.CharField()
+ >>> data = {'name': '', 'url': '', 'comment': 'Foo'}
+ >>> f = CommentForm(data)
+ >>> f.is_valid()
+ False
+ # The form does *not* fall back to using the initial values.
+ >>> f.errors
+ {'url': [u'This field is required.'], 'name': [u'This field is required.']}
+
+``widget``
+~~~~~~~~~~
+
+The ``widget`` argument lets you specify a ``Widget`` class to use when
+rendering this ``Field``. See "Widgets" below for more information.
+
+``help_text``
+~~~~~~~~~~~~~
+
+The ``help_text`` argument lets you specify descriptive text for this
+``Field``. If you provide ``help_text``, it will be displayed next to the
+``Field`` when the ``Field`` is rendered by one of the convenience ``Form``
+methods (e.g., ``as_ul()``).
+
+Here's a full example ``Form`` that implements ``help_text`` for two of its
+fields. We've specified ``auto_id=False`` to simplify the output::
+
+ >>> class HelpTextContactForm(forms.Form):
+ ... subject = forms.CharField(max_length=100, help_text='100 characters max.')
+ ... message = forms.CharField()
+ ... sender = forms.EmailField(help_text='A valid e-mail address, please.')
+ ... cc_myself = forms.BooleanField()
+ >>> f = HelpTextContactForm(auto_id=False)
+ >>> print f.as_table()
+ <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr>
+ <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
+ <tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr>
+ <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
+ >>> print f.as_ul()
+ <li>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li>
+ <li>Message: <input type="text" name="message" /></li>
+ <li>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li>
+ <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
+ >>> print f.as_p()
+ <p>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p>
+ <p>Message: <input type="text" name="message" /></p>
+ <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p>
+ <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
+
+Dynamic initial values
+----------------------
+
+The ``initial`` argument to ``Field`` (explained above) lets you hard-code the
+initial value for a ``Field`` -- but what if you want to declare the initial
+value at runtime? For example, you might want to fill in a ``username`` field
+with the username of the current session.
+
+To accomplish this, use the ``initial`` argument to a ``Form``. This argument,
+if given, should be a dictionary mapping field names to initial values. Only
+include the fields for which you're specifying an initial value; it's not
+necessary to include every field in your form. For example::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField()
+ ... url = forms.URLField()
+ ... comment = forms.CharField()
+ >>> f = CommentForm(initial={'name': 'your username'}, auto_id=False)
+ >>> print f
+ <tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr>
+ <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+ >>> f = CommentForm(initial={'name': 'another username'}, auto_id=False)
+ >>> print f
+ <tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr>
+ <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+
+Just like the ``initial`` parameter to ``Field``, these values are only
+displayed for unbound forms, and they're not used as fallback values if a
+particular value isn't provided.
+
+Finally, note that if a ``Field`` defines ``initial`` *and* you include
+``initial`` when instantiating the ``Form``, then the latter ``initial`` will
+have precedence. In this example, ``initial`` is provided both at the field
+level and at the form instance level, and the latter gets precedence::
+
+ >>> class CommentForm(forms.Form):
+ ... name = forms.CharField(initial='class')
+ ... url = forms.URLField()
+ ... comment = forms.CharField()
+ >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
+ >>> print f
+ <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
+ <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
+ <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
+
+Built-in ``Field`` classes
+--------------------------
+
+Naturally, the ``newforms`` library comes with a set of ``Field`` classes that
+represent common validation needs. This section documents each built-in field.
+
+For each field, we describe the default widget used if you don't specify
+``widget``. We also specify the value returned when you provide an empty value
+(see the section on ``required`` above to understand what that means).
+
+``BooleanField``
+~~~~~~~~~~~~~~~~
+
+ * Default widget: ``CheckboxInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``True`` or ``False`` value.
+ * Validates nothing (i.e., it never raises a ``ValidationError``).
+
+``CharField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates nothing, unless ``max_length`` or ``min_length`` is provided.
+
+Has two optional arguments for validation, ``max_length`` and ``min_length``.
+If provided, these arguments ensure that the string is at most or at least the
+given length.
+
+``ChoiceField``
+~~~~~~~~~~~~~~~
+
+ * Default widget: ``Select``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value exists in the list of choices.
+
+Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
+tuple) of 2-tuples to use as choices for this field.
+
+``DateField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.date`` object.
+ * Validates that the given value is either a ``datetime.date``,
+ ``datetime.datetime`` or string formatted in a particular date format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.date`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
+ '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
+ '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
+ '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
+ '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
+
+``DateTimeField``
+~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.datetime`` object.
+ * Validates that the given value is either a ``datetime.datetime``,
+ ``datetime.date`` or string formatted in a particular datetime format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.datetime`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
+ '%Y-%m-%d %H:%M', # '2006-10-25 14:30'
+ '%Y-%m-%d', # '2006-10-25'
+ '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
+ '%m/%d/%Y %H:%M', # '10/25/2006 14:30'
+ '%m/%d/%Y', # '10/25/2006'
+ '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
+ '%m/%d/%y %H:%M', # '10/25/06 14:30'
+ '%m/%d/%y', # '10/25/06'
+
+``EmailField``
+~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value is a valid e-mail address, using a
+ moderately complex regular expression.
+
+Has two optional arguments for validation, ``max_length`` and ``min_length``.
+If provided, these arguments ensure that the string is at most or at least the
+given length.
+
+``IntegerField``
+~~~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python integer or long integer.
+ * Validates that the given value is an integer. Leading and trailing
+ whitespace is allowed, as in Python's ``int()`` function.
+
+``MultipleChoiceField``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``SelectMultiple``
+ * Empty value: ``[]`` (an empty list)
+ * Normalizes to: A list of Unicode objects.
+ * Validates that every value in the given list of values exists in the list
+ of choices.
+
+Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
+tuple) of 2-tuples to use as choices for this field.
+
+``NullBooleanField``
+~~~~~~~~~~~~~~~~~~~~
+
+ * Default widget: ``NullBooleanSelect``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``True``, ``False`` or ``None`` value.
+ * Validates nothing (i.e., it never raises a ``ValidationError``).
+
+``RegexField``
+~~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value matches against a certain regular
+ expression.
+
+Takes one required argument, ``regex``, which is a regular expression specified
+either as a string or a compiled regular expression object.
+
+Also takes the following optional arguments:
+
+ ====================== =====================================================
+ Argument Description
+ ====================== =====================================================
+ ``max_length`` Ensures the string has at most this many characters.
+ ``min_length`` Ensures the string has at least this many characters.
+ ``error_message`` Error message to return for failed validation. If no
+ message is provided, a generic error message will be
+ used.
+ ====================== =====================================================
+
+``TimeField``
+~~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``None``
+ * Normalizes to: A Python ``datetime.time`` object.
+ * Validates that the given value is either a ``datetime.time`` or string
+ formatted in a particular time format.
+
+Takes one optional argument, ``input_formats``, which is a list of formats used
+to attempt to convert a string to a valid ``datetime.time`` object.
+
+If no ``input_formats`` argument is provided, the default input formats are::
+
+ '%H:%M:%S', # '14:30:59'
+ '%H:%M', # '14:30'
+
+``URLField``
+~~~~~~~~~~~~
+
+ * Default widget: ``TextInput``
+ * Empty value: ``''`` (an empty string)
+ * Normalizes to: A Unicode object.
+ * Validates that the given value is a valid URL.
+
+Takes the following optional arguments:
+
+ ======================== =====================================================
+ Argument Description
+ ======================== =====================================================
+ ``max_length`` Ensures the string has at most this many characters.
+ ``min_length`` Ensures the string has at least this many characters.
+ ``verify_exists`` If ``True``, the validator will attempt to load the
+ given URL, raising ``ValidationError`` if the page
+ gives a 404. Defaults to ``False``.
+ ``validator_user_agent`` String used as the user-agent used when checking for
+ a URL's existence. Defaults to the value of the
+ ``URL_VALIDATOR_USER_AGENT`` setting.
+ ======================== =====================================================
+
+Slightly complex built-in ``Field`` classes
+-------------------------------------------
+
+The following are not yet documented here. See the unit tests, linked-to from
+the bottom of this document, for examples of their use.
+
+``ComboField``
+~~~~~~~~~~~~~~
+
+``MultiValueField``
+~~~~~~~~~~~~~~~~~~~
+
+``SplitDateTimeField``
+~~~~~~~~~~~~~~~~~~~~~~
+
+Creating custom fields
+----------------------
+
+If the built-in ``Field`` classes don't meet your needs, you can easily create
+custom ``Field`` classes. To do this, just create a subclass of
+``django.newforms.Field``. Its only requirements are that it implement a
+``clean()`` method and that its ``__init__()`` method accept the core arguments
+mentioned above (``required``, ``label``, ``initial``, ``widget``,
+``help_text``).
+
+Custom form and field validation
+---------------------------------
+
+Form validation happens when the data is cleaned. If you want to customise
+this process, there are various places you can change, each one serving a
+different purpose. Thee types of cleaning methods are run during form
+processing. These are normally executed when you call the ``is_valid()``
+method on a form. There are other things that can trigger cleaning and
+validation (accessing the ``errors`` attribute or calling ``full_clean()``
+directly), but normally they won't be needed.
+
+In general, any cleaning method can raise ``ValidationError`` if there is a
+problem with the data it is processing, passing the relevant error message to
+the ``ValidationError`` constructor. If no ``ValidationError`` is raised, the
+method should return the cleaned (normalised) data as a Python object.
+
+If you detect multiple errors during a cleaning method and wish to signal all
+of them to the form submitter, it is possible to pass a list of errors to the
+``ValidationError`` constructor.
+
+The three types of cleaning methods are:
+
+ * The ``clean()`` method on a Field subclass. This is responsible
+ for cleaning the data in a way that is generic for that type of field.
+ For example, a FloatField will turn the data into a Python ``float`` or
+ raise a ``ValidationError``.
+
+ * The ``clean_<fieldname>()`` method in a form subclass -- where
+ ``<fieldname>`` is replaced with the name of the form field attribute.
+ This method does any cleaning that is specific to that particular
+ attribute, unrelated to the type of field that it is. This method is not
+ passed any parameters. You will need to look up the value of the field
+ in ``self.cleaned_data`` and remember that it will be a Python object
+ at this point, not the original string submitted in the form (it will be
+ in ``cleaned_data`` because the general field ``clean()`` method, above,
+ has already cleaned the data once).
+
+ For example, if you wanted to validate that the contents of a
+ ``CharField`` called ``serialnumber`` was unique,
+ ``clean_serialnumber()`` would be the right place to do this. You don't
+ need a specific field (it's just a ``CharField``), but you want a
+ formfield-specific piece of validation and, possibly,
+ cleaning/normalizing the data.
+
+ * The Form subclass's ``clean()`` method. This method can perform
+ any validation that requires access to multiple fields from the form at
+ once. This is where you might put in things to check that if field ``A``
+ is supplied, field ``B`` must contain a valid email address and the
+ like. The data that this method returns is the final ``cleaned_data``
+ attribute for the form, so don't forget to return the full list of
+ cleaned data if you override this method (by default, ``Form.clean()``
+ just returns ``self.cleaned_data``).
+
+ Note that any errors raised by your ``Form.clean()`` override will not
+ be associated with any field in particular. They go into a special
+ "field" (called ``__all__``, which you can access via the
+ ``non_field_errors()`` method if you need to.
+
+These methods are run in the order given above, one field at a time. That is,
+for each field in the form (in the order they are declared in the form
+definition), the ``Field.clean()`` method (or it's override) is run, then
+``clean_<fieldname>()``. Finally, once those two methods are run for every
+field, the ``Form.clean()`` method, or it's override, is executed.
+
+As mentioned above, any of these methods can raise a ``ValidationError``. For
+any field, if the ``Field.clean()`` method raises a ``ValidationError``, any
+field-specific cleaning method is not called. However, the cleaning methods
+for all remaining fields are still executed.
+
+The ``clean()`` method for the ``Form`` class or subclass is always run. If
+that method raises a ``ValidationError``, ``cleaned_data`` will be an empty
+dictionary.
+
+The previous paragraph means that if you are overriding ``Form.clean()``, you
+should iterate through ``self.cleaned_data.items()``, possibly considering the
+``_errors`` dictionary attribute on the form as well. In this way, you will
+already know which fields have passed their individual validation requirements.
+
+A simple example
+~~~~~~~~~~~~~~~~
+
+Here's a simple example of a custom field that validates its input is a string
+containing comma-separated e-mail addresses, with at least one address. We'll
+keep it simple and assume e-mail validation is contained in a function called
+``is_valid_email()``. The full class::
+
+ from django import newforms as forms
+
+ class MultiEmailField(forms.Field):
+ def clean(self, value):
+ emails = value.split(',')
+ for email in emails:
+ if not is_valid_email(email):
+ raise forms.ValidationError('%s is not a valid e-mail address.' % email)
+ if not emails:
+ raise forms.ValidationError('Enter at least one e-mail address.')
+ return emails
+
+Let's alter the ongoing ``ContactForm`` example to demonstrate how you'd use
+this in a form. Simply use ``MultiEmailField`` instead of ``forms.EmailField``,
+like so::
+
+ class ContactForm(forms.Form):
+ subject = forms.CharField(max_length=100)
+ message = forms.CharField()
+ senders = MultiEmailField()
+ cc_myself = forms.BooleanField()
+
+Generating forms for models
+===========================
+
+If you're building a database-driven app, chances are you'll have forms that
+map closely to Django models. For instance, you might have a ``BlogComment``
+model, and you want to create a form that lets people submit comments. In this
+case, it would be redundant to define the field types in your form, because
+you've already defined the fields in your model.
+
+For this reason, Django provides a few helper functions that let you create a
+``Form`` class from a Django model.
+
+``form_for_model()``
+--------------------
+
+The method ``django.newforms.form_for_model()`` creates a form based on the
+definition of a specific model. Pass it the model class, and it will return a
+``Form`` class that contains a form field for each model field.
+
+For example::
+
+ >>> from django.newforms import form_for_model
+
+ # Create the form class.
+ >>> ArticleForm = form_for_model(Article)
+
+ # Create an empty form instance.
+ >>> f = ArticleForm()
+
+It bears repeating that ``form_for_model()`` takes the model *class*, not a
+model instance, and it returns a ``Form`` *class*, not a ``Form`` instance.
+
+Field types
+~~~~~~~~~~~
+
+The generated ``Form`` class will have a form field for every model field. Each
+model field has a corresponding default form field. For example, a
+``CharField`` on a model is represented as a ``CharField`` on a form. A
+model ``ManyToManyField`` is represented as a ``MultipleChoiceField``. Here is
+the full list of conversions:
+
+ =============================== ========================================
+ Model field Form field
+ =============================== ========================================
+ ``AutoField`` Not represented in the form
+ ``BooleanField`` ``BooleanField``
+ ``CharField`` ``CharField`` with ``max_length`` set to
+ the model field's ``maxlength``
+ ``CommaSeparatedIntegerField`` ``CharField``
+ ``DateField`` ``DateField``
+ ``DateTimeField`` ``DateTimeField``
+ ``DecimalField`` ``DecimalField``
+ ``EmailField`` ``EmailField``
+ ``FileField`` ``CharField``
+ ``FilePathField`` ``CharField``
+ ``FloatField`` ``FloatField``
+ ``ForeignKey`` ``ModelChoiceField`` (see below)
+ ``ImageField`` ``CharField``
+ ``IntegerField`` ``IntegerField``
+ ``IPAddressField`` ``CharField``
+ ``ManyToManyField`` ``ModelMultipleChoiceField`` (see
+ below)
+ ``NullBooleanField`` ``CharField``
+ ``PhoneNumberField`` ``USPhoneNumberField``
+ (from ``django.contrib.localflavor.us``)
+ ``PositiveIntegerField`` ``IntegerField``
+ ``PositiveSmallIntegerField`` ``IntegerField``
+ ``SlugField`` ``CharField``
+ ``SmallIntegerField`` ``IntegerField``
+ ``TextField`` ``CharField`` with ``widget=Textarea``
+ ``TimeField`` ``TimeField``
+ ``URLField`` ``URLField`` with ``verify_exists`` set
+ to the model field's ``verify_exists``
+ ``USStateField`` ``CharField`` with
+ ``widget=USStateSelect``
+ (``USStateSelect`` is from
+ ``django.contrib.localflavor.us``)
+ ``XMLField`` ``CharField`` with ``widget=Textarea``
+ =============================== ========================================
+
+
+.. note::
+ The ``FloatField`` form field and ``DecimalField`` model and form fields
+ are new in the development version.
+
+As you might expect, the ``ForeignKey`` and ``ManyToManyField`` model field
+types are special cases:
+
+ * ``ForeignKey`` is represented by ``django.newforms.ModelChoiceField``,
+ which is a ``ChoiceField`` whose choices are a model ``QuerySet``.
+
+ * ``ManyToManyField`` is represented by
+ ``django.newforms.ModelMultipleChoiceField``, which is a
+ ``MultipleChoiceField`` whose choices are a model ``QuerySet``.
+
+In addition, each generated form field has attributes set as follows:
+
+ * If the model field has ``blank=True``, then ``required`` is set to
+ ``False`` on the form field. Otherwise, ``required=True``.
+
+ * The form field's ``label`` is set to the ``verbose_name`` of the model
+ field, with the first character capitalized.
+
+ * The form field's ``help_text`` is set to the ``help_text`` of the model
+ field.
+
+ * If the model field has ``choices`` set, then the form field's ``widget``
+ will be set to ``Select``, with choices coming from the model field's
+ ``choices``.
+
+Finally, note that you can override the form field used for a given model
+field. See "Overriding the default field types" below.
+
+A full example
+~~~~~~~~~~~~~~
+
+Consider this set of models::
+
+ from django.db import models
+
+ TITLE_CHOICES = (
+ ('MR', 'Mr.'),
+ ('MRS', 'Mrs.'),
+ ('MS', 'Ms.'),
+ )
+
+ class Author(models.Model):
+ name = models.CharField(maxlength=100)
+ title = models.CharField(maxlength=3, choices=TITLE_CHOICES)
+ birth_date = models.DateField(blank=True, null=True)
+
+ def __str__(self):
+ return self.name
+
+ class Book(models.Model):
+ name = models.CharField(maxlength=100)
+ authors = models.ManyToManyField(Author)
+
+With these models, a call to ``form_for_model(Author)`` would return a ``Form``
+class equivalent to this::
+
+ class AuthorForm(forms.Form):
+ name = forms.CharField(max_length=100)
+ title = forms.CharField(max_length=3,
+ widget=forms.Select(choices=TITLE_CHOICES))
+ birth_date = forms.DateField(required=False)
+
+A call to ``form_for_model(Book)`` would return a ``Form`` class equivalent to
+this::
+
+ class BookForm(forms.Form):
+ name = forms.CharField(max_length=100)
+ authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
+
+The ``save()`` method
+~~~~~~~~~~~~~~~~~~~~~
+
+Every form produced by ``form_for_model()`` also has a ``save()`` method. This
+method creates and saves a database object from the data bound to the form. For
+example::
+
+ # Create a form instance from POST data.
+ >>> f = ArticleForm(request.POST)
+
+ # Save a new Article object from the form's data.
+ >>> new_article = f.save()
+
+Note that ``save()`` will raise a ``ValueError`` if the data in the form
+doesn't validate -- i.e., ``if form.errors``.
+
+Using an alternate base class
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you want to add custom methods to the form generated by
+``form_for_model()``, write a class that extends ``django.newforms.BaseForm``
+and contains your custom methods. Then, use the ``form`` argument to
+``form_for_model()`` to tell it to use your custom form as its base class.
+For example::
+
+ # Create the new base class.
+ >>> class MyBase(BaseForm):
+ ... def my_method(self):
+ ... # Do whatever the method does
+
+ # Create the form class with a different base class.
+ >>> ArticleForm = form_for_model(Article, form=MyBase)
+
+ # Instantiate the form.
+ >>> f = ArticleForm()
+
+ # Use the base class method.
+ >>> f.my_method()
+
+Using a subset of fields on the form
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+In some cases, you may not want all the model fields to appear on the generated
+form. There are two ways of telling ``form_for_model()`` to use only a subset
+of the model fields:
+
+ 1. Set ``editable=False`` on the model field. As a result, *any* form
+ created from the model via ``form_for_model()`` will not include that
+ field.
+
+ 2. Use the ``fields`` argument to ``form_for_model()``. This argument, if
+ given, should be a list of field names to include in the form.
+
+ For example, if you want a form for the ``Author`` model (defined above)
+ that includes only the ``name`` and ``title`` fields, you would specify
+ ``fields`` like this::
+
+ PartialArticleForm = form_for_model(Author, fields=('name', 'title'))
+
+.. note::
+
+ If you specify ``fields`` when creating a form with ``form_for_model()``,
+ make sure that the fields that are *not* specified can provide default
+ values, or are allowed to have a value of ``None``. If a field isn't
+ specified on a form, the object created from the form can't provide
+ a value for that attribute, which will prevent the new instance from
+ being saved.
+
+Overriding the default field types
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The default field types, as described in the "Field types" table above, are
+sensible defaults; if you have a ``DateField`` in your model, chances are you'd
+want that to be represented as a ``DateField`` in your form. But
+``form_for_model()`` gives you the flexibility of changing the form field type
+for a given model field. You do this by specifying a **formfield callback**.
+
+A formfield callback is a function that, when provided with a model field,
+returns a form field instance. When constructing a form, ``form_for_model()``
+asks the formfield callback to provide form field types.
+
+By default, ``form_for_model()`` calls the ``formfield()`` method on the model
+field::
+
+ def default_callback(field, **kwargs):
+ return field.formfield(**kwargs)
+
+The ``kwargs`` are any keyword arguments that might be passed to the form
+field, such as ``required=True`` or ``label='Foo'``.
+
+For example, if you wanted to use ``MyDateFormField`` for any ``DateField``
+field on the model, you could define the callback::
+
+ >>> def my_callback(field, **kwargs):
+ ... if isinstance(field, models.DateField):
+ ... return MyDateFormField(**kwargs)
+ ... else:
+ ... return field.formfield(**kwargs)
+
+ >>> ArticleForm = form_for_model(formfield_callback=my_callback)
+
+Note that your callback needs to handle *all* possible model field types, not
+just the ones that you want to behave differently to the default. That's why
+this example has an ``else`` clause that implements the default behavior.
+
+Finding the model associated with a form
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The model class that was used to construct the form is available
+using the ``_model`` property of the generated form::
+
+ >>> ArticleForm = form_for_model(Article)
+ >>> ArticleForm._model
+ <class 'myapp.models.Article'>
+
+``form_for_instance()``
+-----------------------
+
+``form_for_instance()`` is like ``form_for_model()``, but it takes a model
+instance instead of a model class::
+
+ # Create an Author.
+ >>> a = Author(name='Joe Smith', title='MR', birth_date=None)
+ >>> a.save()
+
+ # Create a form for this particular Author.
+ >>> AuthorForm = form_for_instance(a)
+
+ # Instantiate the form.
+ >>> f = AuthorForm()
+
+When a form created by ``form_for_instance()`` is created, the initial
+data values for the form fields are drawn from the instance. However,
+this data is not bound to the form. You will need to bind data to the
+form before the form can be saved.
+
+When you call ``save()`` on a form created by ``form_for_instance()``,
+the database instance will be updated. As in ``form_for_model()``, ``save()``
+will raise ``ValueError`` if the data doesn't validate.
+
+``form_for_instance()`` has ``form``, ``fields`` and ``formfield_callback``
+arguments that behave the same way as they do for ``form_for_model()``.
+
+When should you use ``form_for_model()`` and ``form_for_instance()``?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The ``form_for_model()`` and ``form_for_instance()`` functions are meant to be
+shortcuts for the common case. If you want to create a form whose fields map to
+more than one model, or a form that contains fields that *aren't* on a model,
+you shouldn't use these shortcuts. Creating a ``Form`` class the "long" way
+isn't that difficult, after all.
+
More coming soon
================
@@ -290,11 +1641,5 @@ http://code.djangoproject.com/browser/django/trunk/tests/regressiontests/forms/t
-- the unit tests for ``django.newforms``. This can give you a good idea of
what's possible.
-Using forms to validate data
-----------------------------
-
-Using forms with templates
-==========================
-
-Using forms in views
-====================
+If you're really itching to learn and use this library, please be patient.
+We're working hard on finishing both the code and documentation.
diff --git a/docs/outputting_csv.txt b/docs/outputting_csv.txt
index 1970261891..d6ec3f62a0 100644
--- a/docs/outputting_csv.txt
+++ b/docs/outputting_csv.txt
@@ -24,7 +24,7 @@ and Django's ``HttpResponse`` objects are file-like objects.
For more information on the CSV library, see the `CSV library docs`_.
- .. _Request and response objects: http://www.djangoproject.com/documentation/request_response/
+ .. _Request and response objects: ../request_response/
.. _CSV library docs: http://www.python.org/doc/current/lib/module-csv.html
Here's an example::
@@ -115,5 +115,5 @@ a line of CSV for each row. It uses the `addslashes template filter`_ to ensure
there aren't any problems with quotes. If you can be certain your data doesn't
have single or double quotes in it, you can remove the ``addslashes`` filters.
-.. _Django template system: http://www.djangoproject.com/documentation/templates/
-.. _addslashes template filter: http://www.djangoproject.com/documentation/templates/#addslashes
+.. _Django template system: ../templates/
+.. _addslashes template filter: ../templates/#addslashes
diff --git a/docs/outputting_pdf.txt b/docs/outputting_pdf.txt
index edd34aca24..bd6ae7a660 100644
--- a/docs/outputting_pdf.txt
+++ b/docs/outputting_pdf.txt
@@ -29,7 +29,7 @@ Test your installation by importing it in the Python interactive interpreter::
If that command doesn't raise any errors, the installation worked.
-.. _user guide: http://www.reportlab.org/rsrc/userguide.pdf
+.. _user guide: http://www.reportlab.com/docs/userguide.pdf
Write your view
===============
@@ -43,7 +43,7 @@ objects.
For more information on ``HttpResponse`` objects, see
`Request and response objects`_.
- .. _Request and response objects: http://www.djangoproject.com/documentation/request_response/
+ .. _Request and response objects: ../request_response/
Here's a "Hello World" example::
diff --git a/docs/overview.txt b/docs/overview.txt
index 8e6274dd9a..7b3559663a 100644
--- a/docs/overview.txt
+++ b/docs/overview.txt
@@ -11,7 +11,7 @@ understand how Django works, but this isn't intended to be a tutorial or
reference. Please see our more-detailed Django documentation_ when you're ready
to start a project.
-.. _documentation: http://www.djangoproject.com/documentation/
+.. _documentation: ../
Design your model
=================
@@ -297,5 +297,5 @@ The next obvious steps are for you to `download Django`_, read `the tutorial`_
and join `the community`_. Thanks for your interest!
.. _download Django: http://www.djangoproject.com/download/
-.. _the tutorial: http://www.djangoproject.com/documentation/tutorial1/
+.. _the tutorial: http://www.djangoproject.com/documentation/tutorial01/
.. _the community: http://www.djangoproject.com/community/
diff --git a/docs/redirects.txt b/docs/redirects.txt
index 13f08668c8..4df60d473f 100644
--- a/docs/redirects.txt
+++ b/docs/redirects.txt
@@ -15,8 +15,8 @@ To install the redirects app, follow these steps:
to your MIDDLEWARE_CLASSES_ setting.
3. Run the command ``manage.py syncdb``.
-.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
-.. _MIDDLEWARE_CLASSES: http://www.djangoproject.com/documentation/settings/#middleware-classes
+.. _INSTALLED_APPS: ../settings/#installed-apps
+.. _MIDDLEWARE_CLASSES: ../settings/#middleware-classes
How it works
============
@@ -46,8 +46,8 @@ resort.
For more on middleware, read the `middleware docs`_.
-.. _SITE_ID: http://www.djangoproject.com/documentation/settings/#site-id
-.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
+.. _SITE_ID: ../settings/#site-id
+.. _middleware docs: ../middleware/
How to add, change and delete redirects
=======================================
@@ -66,6 +66,6 @@ Redirects are represented by a standard `Django model`_, which lives in
`django/contrib/redirects/models.py`_. You can access redirect
objects via the `Django database API`_.
-.. _Django model: http://www.djangoproject.com/documentation/model_api/
+.. _Django model: ../model-api/
.. _django/contrib/redirects/models.py: http://code.djangoproject.com/browser/django/trunk/django/contrib/redirects/models.py
-.. _Django database API: http://www.djangoproject.com/documentation/db_api/
+.. _Django database API: ../db-api/
diff --git a/docs/release_notes_0.96.txt b/docs/release_notes_0.96.txt
new file mode 100644
index 0000000000..f62780c6b2
--- /dev/null
+++ b/docs/release_notes_0.96.txt
@@ -0,0 +1,264 @@
+=================================
+Django version 0.96 release notes
+=================================
+
+Welcome to Django 0.96!
+
+The primary goal for 0.96 is a cleanup and stabilization of the features
+introduced in 0.95. There have been a few small `backwards-incompatible
+changes`_ since 0.95, but the upgrade process should be fairly simple
+and should not require major changes to existing applications.
+
+However, we're also releasing 0.96 now because we have a set of
+backwards-incompatible changes scheduled for the near future. Once
+completed, they will involve some code changes for application
+developers, so we recommend that you stick with Django 0.96 until the
+next official release; then you'll be able to upgrade in one step
+instead of needing to make incremental changes to keep up with the
+development version of Django.
+
+Backwards-incompatible changes
+==============================
+
+The following changes may require you to update your code when you switch from
+0.95 to 0.96:
+
+``MySQLdb`` version requirement
+-------------------------------
+
+Due to a bug in older versions of the ``MySQLdb`` Python module (which
+Django uses to connect to MySQL databases), Django's MySQL backend now
+requires version 1.2.1p2 or higher of `MySQLdb`, and will raise
+exceptions if you attempt to use an older version.
+
+If you're currently unable to upgrade your copy of ``MySQLdb`` to meet
+this requirement, a separate, backwards-compatible backend, called
+"mysql_old", has been added to Django. To use this backend, change
+the ``DATABASE_ENGINE`` setting in your Django settings file from
+this::
+
+ DATABASE_ENGINE = "mysql"
+
+to this::
+
+ DATABASE_ENGINE = "mysql_old"
+
+However, we strongly encourage MySQL users to upgrade to a more recent
+version of `MySQLdb` as soon as possible, The "mysql_old" backend is
+provided only to ease this transition, and is considered deprecated;
+aside from any necessary security fixes, it will not be actively
+maintained, and it will be removed in a future release of Django.
+
+Also, note that some features, like the new ``DATABASE_OPTIONS``
+setting (see the `databases documentation`_ for details), are only
+available on the "mysql" backend, and will not be made available for
+"mysql_old".
+
+.. _databases documentation: ../databases/
+
+Database constraint names changed
+---------------------------------
+
+The format of the constraint names Django generates for foreign key
+references have changed slightly. These names are generally only used
+when it is not possible to put the reference directly on the affected
+column, so they are not always visible.
+
+The effect of this change is that running ``manage.py reset`` and
+similar commands against an existing database may generate SQL with
+the new form of constraint name, while the database itself contains
+constraints named in the old form; this will cause the database server
+to raise an error message about modifying non-existent constraints.
+
+If you need to work around this, there are two methods available:
+
+ 1. Redirect the output of ``manage.py`` to a file, and edit the
+ generated SQL to use the correct constraint names before
+ executing it.
+
+ 2. Examine the output of ``manage.py sqlall`` to see the new-style
+ constraint names, and use that as a guide to rename existing
+ constraints in your database.
+
+Name changes in ``manage.py``
+-----------------------------
+
+A few of the options to ``manage.py`` have changed with the addition of fixture
+support:
+
+ * There are new ``dumpdata`` and ``loaddata`` commands which, as
+ you might expect, will dump and load data to/from the
+ database. These commands can operate against any of Django's
+ supported serialization formats.
+
+ * The ``sqlinitialdata`` command has been renamed to ``sqlcustom`` to
+ emphasize that ``loaddata`` should be used for data (and ``sqlcustom`` for
+ other custom SQL -- views, stored procedures, etc.).
+
+ * The vestigial ``install`` command has been removed. Use ``syncdb``.
+
+Backslash escaping changed
+--------------------------
+
+The Django database API now escapes backslashes given as query parameters. If
+you have any database API code that matches backslashes, and it was working before
+(despite the lack of escaping), you'll have to change your code to "unescape" the
+slashes one level.
+
+For example, this used to work::
+
+ # Find text containing a single backslash
+ MyModel.objects.filter(text__contains='\\\\')
+
+The above is now incorrect, and should be rewritten as::
+
+ # Find text containing a single backslash
+ MyModel.objects.filter(text__contains='\\')
+
+Removed ENABLE_PSYCO setting
+----------------------------
+
+The ``ENABLE_PSYCO`` setting no longer exists. If your settings file includes
+``ENABLE_PSYCO`` it will have no effect; to use Psyco_, we recommend
+writing a middleware class to activate it.
+
+.. _psyco: http://psyco.sourceforge.net/
+
+What's new in 0.96?
+===================
+
+This revision represents over a thousand source commits and over four hundred
+bug fixes, so we can't possibly catalog all the changes. Here, we describe the
+most notable changes in this release.
+
+New forms library
+-----------------
+
+``django.newforms`` is Django's new form-handling library. It's a
+replacement for ``django.forms``, the old form/manipulator/validation
+framework. Both APIs are available in 0.96, but over the next two
+releases we plan to switch completely to the new forms system, and
+deprecate and remove the old system.
+
+There are three elements to this transition:
+
+ * We've copied the current ``django.forms`` to
+ ``django.oldforms``. This allows you to upgrade your code *now*
+ rather than waiting for the backwards-incompatible change and
+ rushing to fix your code after the fact. Just change your
+ import statements like this::
+
+ from django import forms # 0.95-style
+ from django import oldforms as forms # 0.96-style
+
+ * The next official release of Django will move the current
+ ``django.newforms`` to ``django.forms``. This will be a
+ backwards-incompatible change, and anyone still using the old
+ version of ``django.forms`` at that time will need to change
+ their import statements as described above.
+
+ * The next release after that will completely remove
+ ``django.oldforms``.
+
+Although the ``newforms`` library will continue to evolve, it's ready for use
+for most common cases. We recommend that anyone new to form handling skip the
+old forms system and start with the new.
+
+For more information about ``django.newforms``, read the `newforms
+documentation`_.
+
+.. _newforms documentation: ../newforms/
+
+URLconf improvements
+--------------------
+
+You can now use any callable as the callback in URLconfs (previously, only
+strings that referred to callables were allowed). This allows a much more
+natural use of URLconfs. For example, this URLconf::
+
+ from django.conf.urls.defaults import *
+
+ urlpatterns = patterns('',
+ ('^myview/$', 'mysite.myapp.views.myview')
+ )
+
+can now be rewritten as::
+
+ from django.conf.urls.defaults import *
+ from mysite.myapp.views import myview
+
+ urlpatterns = patterns('',
+ ('^myview/$', myview)
+ )
+
+One useful application of this can be seen when using decorators; this
+change allows you to apply decorators to views *in your
+URLconf*. Thus, you can make a generic view require login very
+easily::
+
+ from django.conf.urls.defaults import *
+ from django.contrib.auth.decorators import login_required
+ from django.views.generic.list_detail import object_list
+ from mysite.myapp.models import MyModel
+
+ info = {
+ "queryset" : MyModel.objects.all(),
+ }
+
+ urlpatterns = patterns('',
+ ('^myview/$', login_required(object_list), info)
+ )
+
+Note that both syntaxes (strings and callables) are valid, and will continue to
+be valid for the foreseeable future.
+
+The test framework
+------------------
+
+Django now includes a test framework so you can start transmuting fear into
+boredom (with apologies to Kent Beck). You can write tests based on doctest_
+or unittest_ and test your views with a simple test client.
+
+There is also new support for "fixtures" -- initial data, stored in any of the
+supported `serialization formats`_, that will be loaded into your database at the
+start of your tests. This makes testing with real data much easier.
+
+See `the testing documentation`_ for the full details.
+
+.. _doctest: http://docs.python.org/lib/module-doctest.html
+.. _unittest: http://docs.python.org/lib/module-unittest.html
+.. _the testing documentation: ../testing/
+.. _serialization formats: ../serialization/
+
+Improvements to the admin interface
+-----------------------------------
+
+A small change, but a very nice one: dedicated views for adding and
+updating users have been added to the admin interface, so you no
+longer need to worry about working with hashed passwords in the admin.
+
+Thanks
+======
+
+Since 0.95, a number of people have stepped forward and taken a major
+new role in Django's development. We'd like to thank these people for
+all their hard work:
+
+ * Russell Keith-Magee and Malcolm Tredinnick for their major code
+ contributions. This release wouldn't have been possible without them.
+
+ * Our new release manager, James Bennett, for his work in getting out
+ 0.95.1, 0.96, and (hopefully) future release.
+
+ * Our ticket managers Chris Beaven (aka SmileyChris), Simon Greenhill,
+ Michael Radziej, and Gary Wilson. They agreed to take on the monumental
+ task of wrangling our tickets into nicely cataloged submission. Figuring
+ out what to work on is now about a million times easier; thanks again,
+ guys.
+
+ * Everyone who submitted a bug report, patch or ticket comment. We can't
+ possibly thank everyone by name -- over 200 developers submitted patches
+ that went into 0.96 -- but everyone who's contributed to Django is listed
+ in AUTHORS_.
+
+.. _AUTHORS: http://code.djangoproject.com/browser/django/trunk/AUTHORS
diff --git a/docs/request_response.txt b/docs/request_response.txt
index 006ac6b648..0b985d563b 100644
--- a/docs/request_response.txt
+++ b/docs/request_response.txt
@@ -93,6 +93,7 @@ All attributes except ``session`` should be considered read-only.
* ``CONTENT_TYPE``
* ``HTTP_ACCEPT_ENCODING``
* ``HTTP_ACCEPT_LANGUAGE``
+ * ``HTTP_HOST`` -- The HTTP Host header sent by the client.
* ``HTTP_REFERER`` -- The referring page, if any.
* ``HTTP_USER_AGENT`` -- The client's user-agent string.
* ``QUERY_STRING`` -- The query string, as a single (unparsed) string.
@@ -117,14 +118,14 @@ All attributes except ``session`` should be considered read-only.
``AuthenticationMiddleware`` activated. For more, see
`Authentication in Web requests`_.
- .. _Authentication in Web requests: http://www.djangoproject.com/documentation/authentication/#authentication-in-web-requests
+ .. _Authentication in Web requests: ../authentication/#authentication-in-web-requests
``session``
A readable-and-writable, dictionary-like object that represents the current
session. This is only available if your Django installation has session
support activated. See the `session documentation`_ for full details.
- .. _`session documentation`: http://www.djangoproject.com/documentation/sessions/
+ .. _`session documentation`: ../sessions/
``raw_post_data``
The raw HTTP POST data. This is only useful for advanced processing. Use
@@ -384,7 +385,6 @@ Methods
Deletes the cookie with the given key. Fails silently if the key doesn't
exist.
- The ``path`` and ``domain`` arguments are new in the Django development version.
Due to the way cookies work, ``path`` and ``domain`` should be the same
values you used in ``set_cookie()`` -- otherwise the cookie may not be deleted.
@@ -417,6 +417,10 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
The constructor doesn't take any arguments. Use this to designate that a
page hasn't been modified since the user's last request.
+``HttpResponseBadRequest``
+ **New in Django development version.**
+ Acts just like ``HttpResponse`` but uses a 400 status code.
+
``HttpResponseNotFound``
Acts just like ``HttpResponse`` but uses a 404 status code.
@@ -432,3 +436,118 @@ types of HTTP responses. Like ``HttpResponse``, these subclasses live in
``HttpResponseServerError``
Acts just like ``HttpResponse`` but uses a 500 status code.
+
+Returning errors
+================
+
+Returning HTTP error codes in Django is easy. We've already mentioned the
+``HttpResponseNotFound``, ``HttpResponseForbidden``,
+``HttpResponseServerError``, etc., subclasses; just return an instance of one
+of those subclasses instead of a normal ``HttpResponse`` in order to signify
+an error. For example::
+
+ def my_view(request):
+ # ...
+ if foo:
+ return HttpResponseNotFound('<h1>Page not found</h1>')
+ else:
+ return HttpResponse('<h1>Page was found</h1>')
+
+Because 404 errors are by far the most common HTTP error, there's an easier way
+to handle those errors.
+
+The Http404 exception
+---------------------
+
+When you return an error such as ``HttpResponseNotFound``, you're responsible
+for defining the HTML of the resulting error page::
+
+ return HttpResponseNotFound('<h1>Page not found</h1>')
+
+For convenience, and because it's a good idea to have a consistent 404 error page
+across your site, Django provides an ``Http404`` exception. If you raise
+``Http404`` at any point in a view function, Django will catch it and return the
+standard error page for your application, along with an HTTP error code 404.
+
+Example usage::
+
+ from django.http import Http404
+
+ def detail(request, poll_id):
+ try:
+ p = Poll.objects.get(pk=poll_id)
+ except Poll.DoesNotExist:
+ raise Http404
+ return render_to_response('polls/detail.html', {'poll': p})
+
+In order to use the ``Http404`` exception to its fullest, you should create a
+template that is displayed when a 404 error is raised. This template should be
+called ``404.html`` and located in the top level of your template tree.
+
+Customizing error views
+-----------------------
+
+The 404 (page not found) view
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+When you raise an ``Http404`` exception, Django loads a special view devoted
+to handling 404 errors. By default, it's the view
+``django.views.defaults.page_not_found``, which loads and renders the template
+``404.html``.
+
+This means you need to define a ``404.html`` template in your root template
+directory. This template will be used for all 404 errors.
+
+This ``page_not_found`` view should suffice for 99% of Web applications, but if
+you want to override the 404 view, you can specify ``handler404`` in your
+URLconf, like so::
+
+ handler404 = 'mysite.views.my_custom_404_view'
+
+Behind the scenes, Django determines the 404 view by looking for ``handler404``.
+By default, URLconfs contain the following line::
+
+ from django.conf.urls.defaults import *
+
+That takes care of setting ``handler404`` in the current module. As you can see
+in ``django/conf/urls/defaults.py``, ``handler404`` is set to
+``'django.views.defaults.page_not_found'`` by default.
+
+Three things to note about 404 views:
+
+ * The 404 view is also called if Django doesn't find a match after checking
+ every regular expression in the URLconf.
+
+ * If you don't define your own 404 view -- and simply use the default,
+ which is recommended -- you still have one obligation: To create a
+ ``404.html`` template in the root of your template directory. The default
+ 404 view will use that template for all 404 errors.
+
+ * If ``DEBUG`` is set to ``True`` (in your settings module) then your 404
+ view will never be used, and the traceback will be displayed instead.
+
+The 500 (server error) view
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Similarly, Django executes special-case behavior in the case of runtime errors
+in view code. If a view results in an exception, Django will, by default, call
+the view ``django.views.defaults.server_error``, which loads and renders the
+template ``500.html``.
+
+This means you need to define a ``500.html`` template in your root template
+directory. This template will be used for all server errors.
+
+This ``server_error`` view should suffice for 99% of Web applications, but if
+you want to override the view, you can specify ``handler500`` in your
+URLconf, like so::
+
+ handler500 = 'mysite.views.my_custom_error_view'
+
+Behind the scenes, Django determines the error view by looking for ``handler500``.
+By default, URLconfs contain the following line::
+
+ from django.conf.urls.defaults import *
+
+That takes care of setting ``handler500`` in the current module. As you can see
+in ``django/conf/urls/defaults.py``, ``handler500`` is set to
+``'django.views.defaults.server_error'`` by default.
diff --git a/docs/serialization.txt b/docs/serialization.txt
index aee1b9a3bb..01afa2708c 100644
--- a/docs/serialization.txt
+++ b/docs/serialization.txt
@@ -27,11 +27,12 @@ data to (see `Serialization formats`_) and a QuerySet_ to serialize.
(Actually, the second argument can be any iterator that yields Django objects,
but it'll almost always be a QuerySet).
-.. _QuerySet: ../db_api/#retrieving-objects
+.. _QuerySet: ../db-api/#retrieving-objects
You can also use a serializer object directly::
- xml_serializer = serializers.get_serializer("xml")
+ XMLSerializer = serializers.get_serializer("xml")
+ xml_serializer = XMLSerializer()
xml_serializer.serialize(queryset)
data = xml_serializer.getvalue()
@@ -43,6 +44,25 @@ This is useful if you want to serialize data directly to a file-like object
.. _HTTPResponse: ../request_response/#httpresponse-objects
+Subset of fields
+~~~~~~~~~~~~~~~~
+
+If you only want a subset of fields to be serialized, you can
+specify a `fields` argument to the serializer::
+
+ from django.core import serializers
+ data = serializers.serialize('xml', SomeModel.objects.all(), fields=('name','size'))
+
+In this example, only the `name` and `size` attributes of each model will
+be serialized.
+
+.. note::
+
+ Depending on your model, you may find that it is not possible to deserialize
+ a model that only serializes a subset of its fields. If a serialized object
+ doesn't specify all the fields that are required by a model, the deserializer
+ will not be able to save deserialized instances.
+
Deserializing data
------------------
@@ -91,10 +111,14 @@ Django "ships" with a few included serializers:
``python`` Translates to and from "simple" Python objects (lists, dicts,
strings, etc.). Not really all that useful on its own, but
used as a base for other serializers.
+
+ ``yaml`` Serializes to YAML (Yet Another Markup Lanuage). This
+ serializer is only available if PyYAML_ is installed.
========== ==============================================================
.. _json: http://json.org/
.. _simplejson: http://undefined.org/python/#simplejson
+.. _PyYAML: http://www.pyyaml.org/
Notes for specific serialization formats
----------------------------------------
@@ -108,7 +132,7 @@ serializer, you must pass ``ensure_ascii=False`` as a parameter to the
For example::
- json_serializer = serializers.get_serializer("json")
+ json_serializer = serializers.get_serializer("json")()
json_serializer.serialize(queryset, ensure_ascii=False, stream=response)
Writing custom serializers
diff --git a/docs/sessions.txt b/docs/sessions.txt
index dd4a581d91..c7124ba703 100644
--- a/docs/sessions.txt
+++ b/docs/sessions.txt
@@ -27,7 +27,7 @@ If you don't want to use sessions, you might as well remove the
``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'``
from your ``INSTALLED_APPS``. It'll save you a small bit of overhead.
-.. _middleware: http://www.djangoproject.com/documentation/middleware/
+.. _middleware: ../middleware/
Using sessions in views
=======================
@@ -107,7 +107,7 @@ posts a comment. It doesn't let a user post a comment more than once::
This simplistic view logs in a "member" of the site::
def login(request):
- m = members.get_object(username__exact=request.POST['username'])
+ m = Member.objects.get(username=request.POST['username'])
if m.password == request.POST['password']:
request.session['member_id'] = m.id
return HttpResponse("You're logged in.")
@@ -158,7 +158,7 @@ is defined in ``django/contrib/sessions/models.py``. Because it's a normal
model, you can access sessions using the normal Django database API::
>>> from django.contrib.sessions.models import Session
- >>> s = Session.objects.get_object(pk='2b1189a188b44ad18c35e113ac6ceead')
+ >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12)
@@ -217,6 +217,23 @@ browser-length cookies -- cookies that expire as soon as the user closes his or
her browser. Use this if you want people to have to log in every time they open
a browser.
+Clearing the session table
+==========================
+
+Note that session data can accumulate in the ``django_session`` database table
+and Django does *not* provide automatic purging. Therefore, it's your job to
+purge expired sessions on a regular basis.
+
+To understand this problem, consider what happens when a user uses a session.
+When a user logs in, Django adds a row to the ``django_session`` database
+table. Django updates this row each time the session data changes. If the user
+logs out manually, Django deletes the row. But if the user does *not* log out,
+the row never gets deleted.
+
+Django provides a sample clean-up script in ``django/bin/daily_cleanup.py``.
+That script deletes any session in the session table whose ``expire_date`` is
+in the past -- but your application may have different requirements.
+
Settings
========
@@ -248,8 +265,6 @@ The name of the cookie to use for sessions. This can be whatever you want.
SESSION_COOKIE_SECURE
---------------------
-**New in Django development version**
-
Default: ``False``
Whether to use a secure cookie for the session cookie. If this is set to
@@ -273,7 +288,7 @@ Whether to save the session data on every request. If this is ``False``
(default), then the session data will only be saved if it has been modified --
that is, if any of its dictionary values have been assigned or deleted.
-.. _Django settings: http://www.djangoproject.com/documentation/settings/
+.. _Django settings: ../settings/
Technical details
=================
diff --git a/docs/settings.txt b/docs/settings.txt
index ba1e8eafea..12e6dab4bc 100644
--- a/docs/settings.txt
+++ b/docs/settings.txt
@@ -59,7 +59,7 @@ Use the ``--settings`` command-line argument to specify the settings manually::
django-admin.py runserver --settings=mysite.settings
-.. _django-admin.py: http://www.djangoproject.com/documentation/django_admin/
+.. _django-admin.py: ../django-admin/
On the server (mod_python)
--------------------------
@@ -75,7 +75,7 @@ settings file to use. Do that with ``SetEnv``::
Read the `Django mod_python documentation`_ for more information.
-.. _Django mod_python documentation: http://www.djangoproject.com/documentation/modpython/
+.. _Django mod_python documentation: ../modpython/
Default settings
================
@@ -102,7 +102,7 @@ between the current settings file and Django's default settings.
For more, see the `diffsettings documentation`_.
-.. _diffsettings documentation: http://www.djangoproject.com/documentation/django_admin/#diffsettings
+.. _diffsettings documentation: ../django-admin/#diffsettings
Using settings in Python code
=============================
@@ -157,15 +157,18 @@ ABSOLUTE_URL_OVERRIDES
Default: ``{}`` (Empty dictionary)
-A dictionary mapping ``"app_label.module_name"`` strings to functions that take
+A dictionary mapping ``"app_label.model_name"`` strings to functions that take
a model object and return its URL. This is a way of overriding
``get_absolute_url()`` methods on a per-installation basis. Example::
ABSOLUTE_URL_OVERRIDES = {
- 'blogs.blogs': lambda o: "/blogs/%s/" % o.slug,
- 'news.stories': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
+ 'blogs.weblog': lambda o: "/blogs/%s/" % o.slug,
+ 'news.story': lambda o: "/stories/%s/%s/" % (o.pub_year, o.slug),
}
+Note that the model name used in this setting should be all lower-case, regardless
+of the case of the actual model class name.
+
ADMIN_FOR
---------
@@ -197,6 +200,9 @@ of (Full name, e-mail address). Example::
(('John', 'john@example.com'), ('Mary', 'mary@example.com'))
+Note that Django will e-mail *all* of these people whenever an error happens. See the
+section on `error reporting via e-mail`_ for more information.
+
ALLOWED_INCLUDE_ROOTS
---------------------
@@ -236,10 +242,11 @@ The cache key prefix that the cache middleware should use. See the
DATABASE_ENGINE
---------------
-Default: ``'postgresql'``
+Default: ``''`` (Empty string)
-Which database backend to use. Either ``'postgresql'``, ``'mysql'``,
-``'sqlite3'`` or ``'ado_mssql'``.
+Which database backend to use. Either ``'postgresql_psycopg2'``,
+``'postgresql'``, ``'mysql'``, ``'mysql_old'``, ``'sqlite3'`` or
+``'ado_mssql'``.
DATABASE_HOST
-------------
@@ -257,6 +264,11 @@ MySQL will connect via a Unix socket to the specified socket. For example::
If you're using MySQL and this value *doesn't* start with a forward slash, then
this value is assumed to be the host.
+If you're using PostgreSQL, an empty string means to use a Unix domain socket
+for the connection, rather than a network connection to localhost. If you
+explictly need to use a TCP/IP connection on the local machine with
+PostgreSQL, specify ``localhost`` here.
+
DATABASE_NAME
-------------
@@ -306,7 +318,7 @@ pages -- and, possibly, by other parts of the system. See
See also DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
-.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
+.. _allowed date format strings: ../templates/#now
DATETIME_FORMAT
---------------
@@ -319,7 +331,7 @@ pages -- and, possibly, by other parts of the system. See
See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and MONTH_DAY_FORMAT.
-.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
+.. _allowed date format strings: ../templates/#now
DEBUG
-----
@@ -328,6 +340,16 @@ Default: ``False``
A boolean that turns on/off debug mode.
+If you define custom settings, django/views/debug.py has a ``HIDDEN_SETTINGS``
+regular expression which will hide from the DEBUG view anything that contins
+``'SECRET``, ``PASSWORD``, or ``PROFANITIES'``. This allows untrusted users to
+be able to give backtraces without seeing sensitive (or offensive) settings.
+
+Still, note that there are always going to be sections of your debug output that
+are inapporpriate for public consumption. File paths, configuration options, and
+the like all give attackers extra information about your server. Never deploy a
+site with ``DEBUG`` turned on.
+
DEFAULT_CHARSET
---------------
@@ -378,8 +400,10 @@ EMAIL_HOST_PASSWORD
Default: ``''`` (Empty string)
-Username to use for the SMTP server defined in ``EMAIL_HOST``. If empty,
-Django won't attempt authentication.
+Password to use for the SMTP server defined in ``EMAIL_HOST``. This setting is
+used in conjunction with ``EMAIL_HOST_USER`` when authenticating to the SMTP
+server. If either of these settings is empty, Django won't attempt
+authenticaion.
See also ``EMAIL_HOST_USER``.
@@ -409,12 +433,32 @@ Subject-line prefix for e-mail messages sent with ``django.core.mail.mail_admins
or ``django.core.mail.mail_managers``. You'll probably want to include the
trailing space.
+EMAIL_USE_TLS
+-------------
+
+**New in Django development version**
+
+Default: ``False``
+
+Whether to use a TLS (secure) connection when talking to the SMTP server.
+
+FIXTURE_DIRS
+-------------
+
+Default: ``()`` (Empty tuple)
+
+List of locations of the fixture data files, in search order. Note that
+these paths should use Unix-style forward slashes, even on Windows. See
+`Testing Django Applications`_.
+
+.. _Testing Django Applications: ../testing/
+
IGNORABLE_404_ENDS
------------------
Default: ``('mail.pl', 'mailform.pl', 'mail.cgi', 'mailform.cgi', 'favicon.ico', '.php')``
-See also ``IGNORABLE_404_STARTS``.
+See also ``IGNORABLE_404_STARTS`` and ``Error reporting via e-mail``.
IGNORABLE_404_STARTS
--------------------
@@ -422,7 +466,8 @@ IGNORABLE_404_STARTS
Default: ``('/cgi-bin/', '/_vti_bin', '/_vti_inf')``
A tuple of strings that specify beginnings of URLs that should be ignored by
-the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS`` and ``IGNORABLE_404_ENDS``.
+the 404 e-mailer. See ``SEND_BROKEN_LINK_EMAILS``, ``IGNORABLE_404_ENDS`` and
+the section on `error reporting via e-mail`_.
INSTALLED_APPS
--------------
@@ -433,7 +478,7 @@ A tuple of strings designating all applications that are enabled in this Django
installation. Each string should be a full Python path to a Python package that
contains a Django application, as created by `django-admin.py startapp`_.
-.. _django-admin.py startapp: http://www.djangoproject.com/documentation/django_admin/#startapp-appname
+.. _django-admin.py startapp: ../django-admin/#startapp-appname
INTERNAL_IPS
------------
@@ -464,49 +509,22 @@ A string representing the language code for this installation. This should be
in standard language format. For example, U.S. English is ``"en-us"``. See the
`internationalization docs`_.
-.. _internationalization docs: http://www.djangoproject.com/documentation/i18n/
+.. _internationalization docs: ../i18n/
LANGUAGES
---------
-Default: A tuple of all available languages. Currently, this is::
+Default: A tuple of all available languages. This list is continually growing
+and including a copy here would inevitably become rapidly out of date. You can
+see the current list of translated languages by looking in
+``django/conf/global_settings.py`` (or view the `online source`_).
- LANGUAGES = (
- ('ar', _('Arabic')),
- ('bn', _('Bengali')),
- ('cs', _('Czech')),
- ('cy', _('Welsh')),
- ('da', _('Danish')),
- ('de', _('German')),
- ('el', _('Greek')),
- ('en', _('English')),
- ('es', _('Spanish')),
- ('es_AR', _('Argentinean Spanish')),
- ('fr', _('French')),
- ('gl', _('Galician')),
- ('hu', _('Hungarian')),
- ('he', _('Hebrew')),
- ('is', _('Icelandic')),
- ('it', _('Italian')),
- ('ja', _('Japanese')),
- ('nl', _('Dutch')),
- ('no', _('Norwegian')),
- ('pt-br', _('Brazilian')),
- ('ro', _('Romanian')),
- ('ru', _('Russian')),
- ('sk', _('Slovak')),
- ('sl', _('Slovenian')),
- ('sr', _('Serbian')),
- ('sv', _('Swedish')),
- ('ta', _('Tamil')),
- ('uk', _('Ukrainian')),
- ('zh-cn', _('Simplified Chinese')),
- ('zh-tw', _('Traditional Chinese')),
- )
+.. _online source: http://code.djangoproject.com/browser/django/trunk/django/conf/global_settings.py
-A tuple of two-tuples in the format (language code, language name). This
-specifies which languages are available for language selection. See the
-`internationalization docs`_ for details.
+The list is a tuple of two-tuples in the format (language code, language
+name) -- for example, ``('ja', 'Japanese')``. This specifies which languages
+are available for language selection. See the `internationalization docs`_ for
+details.
Generally, the default value should suffice. Only set this setting if you want
to restrict language selection to a subset of the Django-provided languages.
@@ -533,6 +551,37 @@ strings for translation, but the translation won't happen at runtime -- so
you'll have to remember to wrap the languages in the *real* ``gettext()`` in
any code that uses ``LANGUAGES`` at runtime.
+LOGIN_REDIRECT_URL
+------------------
+
+**New in Django development version**
+
+Default: ``'/accounts/profile/'``
+
+The URL where requests are redirected after login when the
+``contrib.auth.login`` view gets no ``next`` parameter.
+
+This is used by the `@login_required`_ decorator, for example.
+
+LOGIN_URL
+---------
+
+**New in Django development version**
+
+Default: ``'/accounts/login/'``
+
+The URL where requests are redirected for login, specially when using the
+`@login_required`_ decorator.
+
+LOGOUT_URL
+----------
+
+**New in Django development version**
+
+Default: ``'/accounts/logout/'``
+
+LOGIN_URL counterpart.
+
MANAGERS
--------
@@ -557,6 +606,11 @@ Default: ``''`` (Empty string)
URL that handles the media served from ``MEDIA_ROOT``.
Example: ``"http://media.lawrence.com"``
+Note that this should have a trailing slash if it has a path component.
+
+Good: ``"http://www.example.com/static/"``
+Bad: ``"http://www.example.com/static"``
+
MIDDLEWARE_CLASSES
------------------
@@ -612,7 +666,7 @@ Default: Not defined
A string representing the full Python import path to your root URLconf. For example:
``"mydjangoapps.urls"``. See `How Django processes a request`_.
-.. _How Django processes a request: http://www.djangoproject.com/documentation/url_dispatch/#how-django-processes-a-request
+.. _How Django processes a request: ../url_dispatch/#how-django-processes-a-request
SECRET_KEY
----------
@@ -631,8 +685,19 @@ Default: ``False``
Whether to send an e-mail to the ``MANAGERS`` each time somebody visits a
Django-powered page that is 404ed with a non-empty referer (i.e., a broken
link). This is only used if ``CommonMiddleware`` is installed (see the
-`middleware docs`_). See also ``IGNORABLE_404_STARTS`` and
-``IGNORABLE_404_ENDS``.
+`middleware docs`_). See also ``IGNORABLE_404_STARTS``,
+``IGNORABLE_404_ENDS`` and the section on `error reporting via e-mail`_
+
+SERIALIZATION_MODULES
+---------------------
+
+Default: Not defined.
+
+A dictionary of modules containing serializer definitions (provided as
+strings), keyed by a string identifier for that serialization type. For
+example, to define a YAML serializer, use::
+
+ SERIALIZATION_MODULES = { 'yaml' : 'path.to.yaml_serializer' }
SERVER_EMAIL
------------
@@ -669,8 +734,6 @@ See the `session docs`_.
SESSION_COOKIE_SECURE
---------------------
-**New in Django development version**
-
Default: ``False``
Whether to use a secure cookie for the session cookie. If this is set to
@@ -704,7 +767,7 @@ and a single database can manage content for multiple sites.
See the `site framework docs`_.
-.. _site framework docs: http://www.djangoproject.com/documentation/sites/
+.. _site framework docs: ../sites/
TEMPLATE_CONTEXT_PROCESSORS
---------------------------
@@ -713,7 +776,8 @@ Default::
("django.core.context_processors.auth",
"django.core.context_processors.debug",
- "django.core.context_processors.i18n")
+ "django.core.context_processors.i18n",
+ "django.core.context_processors.media")
A tuple of callables that are used to populate the context in ``RequestContext``.
These callables take a request object as their argument and return a dictionary
@@ -760,32 +824,59 @@ Default: ``''`` (Empty string)
Output, as a string, that the template system should use for invalid (e.g.
misspelled) variables. See `How invalid variables are handled`_.
-.. _How invalid variables are handled: http://www.djangoproject.com/documentation/templates_python/#how-invalid-variables-are-handled
+.. _How invalid variables are handled: ../templates_python/#how-invalid-variables-are-handled
-TEST_RUNNER
------------
+TEST_DATABASE_CHARSET
+---------------------
**New in Django development version**
-Default: ``'django.test.simple.run_tests'``
+Default: ``None``
-The name of the method to use for starting the test suite. See
-`Testing Django Applications`_.
+The character set encoding used to create the test database. The value of this
+string is passed directly through to the database, so its format is
+backend-specific.
-.. _Testing Django Applications: ../testing/
+Supported for the PostgreSQL_ (``postgresql``, ``postgresql_psycopg2``) and MySQL_ (``mysql``, ``mysql_old``) backends.
-TEST_DATABASE_NAME
-------------------
+.. _PostgreSQL: http://www.postgresql.org/docs/8.2/static/multibyte.html
+.. _MySQL: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
+
+TEST_DATABASE_COLLATION
+------------------------
**New in Django development version**
Default: ``None``
-The name of database to use when running the test suite. If a value of
+The collation order to use when creating the test database. This value is
+passed directly to the backend, so its format is backend-specific.
+
+Only supported for ``mysql`` and ``mysql_old`` backends (see `section 10.3.2`_
+of the MySQL manual for details).
+
+.. _section 10.3.2: http://www.mysql.org/doc/refman/5.0/en/charset-database.html
+
+TEST_DATABASE_NAME
+------------------
+
+Default: ``None``
+
+The name of database to use when running the test suite. If a value of
``None`` is specified, the test database will use the name ``'test_' + settings.DATABASE_NAME``. See `Testing Django Applications`_.
.. _Testing Django Applications: ../testing/
+TEST_RUNNER
+-----------
+
+Default: ``'django.test.simple.run_tests'``
+
+The name of the method to use for starting the test suite. See
+`Testing Django Applications`_.
+
+.. _Testing Django Applications: ../testing/
+
TIME_FORMAT
-----------
@@ -798,7 +889,7 @@ pages -- and, possibly, by other parts of the system. See
See also DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT, YEAR_MONTH_FORMAT and
MONTH_DAY_FORMAT.
-.. _allowed date format strings: http://www.djangoproject.com/documentation/templates/#now
+.. _allowed date format strings: ../templates/#now
TIME_ZONE
---------
@@ -822,6 +913,11 @@ manual configuration option (see below), Django will *not* touch the ``TZ``
environment variable, and it'll be up to you to ensure your processes are
running in the correct environment.
+.. note::
+ Django cannot reliably use alternate time zones in a Windows environment.
+ If you're running Django on Windows, this variable must be set to match the
+ system timezone.
+
URL_VALIDATOR_USER_AGENT
------------------------
@@ -830,7 +926,7 @@ Default: ``Django/<version> (http://www.djangoproject.com/)``
The string to use as the ``User-Agent`` header when checking to see if URLs
exist (see the ``verify_exists`` option on URLField_).
-.. _URLField: ../model_api/#urlfield
+.. _URLField: ../model-api/#urlfield
USE_ETAGS
---------
@@ -868,11 +964,11 @@ Different locales have different formats. For example, U.S. English would say
See `allowed date format strings`_. See also DATE_FORMAT, DATETIME_FORMAT,
TIME_FORMAT and MONTH_DAY_FORMAT.
-.. _cache docs: http://www.djangoproject.com/documentation/cache/
-.. _middleware docs: http://www.djangoproject.com/documentation/middleware/
-.. _session docs: http://www.djangoproject.com/documentation/sessions/
+.. _cache docs: ../cache/
+.. _middleware docs: ../middleware/
+.. _session docs: ../sessions/
.. _See available choices: http://www.postgresql.org/docs/8.1/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE
-.. _template documentation: http://www.djangoproject.com/documentation/templates_python/
+.. _template documentation: ../templates_python/
Creating your own settings
==========================
@@ -967,3 +1063,38 @@ Also, it's an error to call ``configure()`` more than once, or to call
It boils down to this: Use exactly one of either ``configure()`` or
``DJANGO_SETTINGS_MODULE``. Not both, and not neither.
+
+.. _@login_required: ../authentication/#the-login-required-decorator
+
+Error reporting via e-mail
+==========================
+
+Server errors
+-------------
+
+When ``DEBUG`` is ``False``, Django will e-mail the users listed in the
+``ADMIN`` setting whenever your code raises an unhandled exception and results
+in an internal server error (HTTP status code 500). This gives the
+administrators immediate notification of any errors.
+
+To disable this behavior, just remove all entries from the ``ADMINS`` setting.
+
+404 errors
+----------
+
+When ``DEBUG`` is ``False`` and your ``MIDDLEWARE_CLASSES`` setting includes
+``CommonMiddleware``, Django will e-mail the users listed in the ``MANAGERS``
+setting whenever your code raises a 404 and the request has a referer.
+(It doesn't bother to e-mail for 404s that don't have a referer.)
+
+You can tell Django to stop reporting particular 404s by tweaking the
+``IGNORABLE_404_ENDS`` and ``IGNORABLE_404_STARTS`` settings. Both should be a
+tuple of strings. For example::
+
+ IGNORABLE_404_ENDS = ('.php', '.cgi')
+ IGNORABLE_404_STARTS = ('/phpmyadmin/',)
+
+In this example, a 404 to any URL ending with ``.php`` or ``.cgi`` will *not*
+be reported. Neither will any URL starting with ``/phpmyadmin/``.
+
+To disable this behavior, just remove all entries from the ``MANAGERS`` setting.
diff --git a/docs/sitemaps.txt b/docs/sitemaps.txt
index 7414567b16..550f448de1 100644
--- a/docs/sitemaps.txt
+++ b/docs/sitemaps.txt
@@ -2,8 +2,6 @@
The sitemap framework
=====================
-**New in Django development version**.
-
Django comes with a high-level sitemap-generating framework that makes
creating sitemap_ XML files easy.
@@ -23,8 +21,8 @@ you express this information in Python code.
It works much like Django's `syndication framework`_. To create a sitemap, just
write a ``Sitemap`` class and point to it in your URLconf_.
-.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+.. _syndication framework: ../syndication/
+.. _URLconf: ../url_dispatch/
Installation
============
@@ -41,9 +39,9 @@ To install the sitemap app, follow these steps:
reason it needs to go into ``INSTALLED_APPS`` is so that the
``load_template_source`` template loader can find the default templates.)
-.. _INSTALLED_APPS: http://www.djangoproject.com/documentation/settings/#installed-apps
-.. _TEMPLATE_LOADERS: http://www.djangoproject.com/documentation/settings/#template-loaders
-.. _sites framework: http://www.djangoproject.com/documentation/sites/
+.. _INSTALLED_APPS: ../settings/#installed-apps
+.. _TEMPLATE_LOADERS: ../settings/#template-loaders
+.. _sites framework: ../sites/
Initialization
==============
@@ -68,7 +66,7 @@ The sitemap view takes an extra, required argument: ``{'sitemaps': sitemaps}``.
``NewsSitemap``). It may also map to an *instance* of a ``Sitemap`` class
(e.g., ``BlogSitemap(some_var)``).
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+.. _URLconf: ../url_dispatch/
Sitemap classes
===============
@@ -217,8 +215,8 @@ defined for the current ``SITE_ID`` (see the `sites documentation`_) and
creates an entry in the sitemap. These entries include only the ``location``
attribute -- not ``lastmod``, ``changefreq`` or ``priority``.
-.. _flatpages: http://www.djangoproject.com/documentation/flatpages/
-.. _sites documentation: http://www.djangoproject.com/documentation/sites/
+.. _flatpages: ../flatpages/
+.. _sites documentation: ../sites/
``GenericSitemap``
------------------
@@ -232,7 +230,7 @@ the ``lastmod`` attribute in the generated sitemap. You may also pass
``priority`` and ``changefreq`` keyword arguments to the ``GenericSitemap``
constructor to specify these attributes for all URLs.
-.. _generic views: http://www.djangoproject.com/documentation/generic_views/
+.. _generic views: ../generic_views/
Example
-------
@@ -261,7 +259,7 @@ Here's an example of a URLconf_ using both::
(r'^sitemap.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps})
)
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+.. _URLconf: ../url_dispatch/
Creating a sitemap index
========================
diff --git a/docs/sites.txt b/docs/sites.txt
index 8c5f1fc64b..12259b04c3 100644
--- a/docs/sites.txt
+++ b/docs/sites.txt
@@ -276,8 +276,8 @@ you want your admin site to have access to all objects (not just site-specific
ones), put ``objects = models.Manager()`` in your model, before you define
``CurrentSiteManager``.
-.. _manager: http://www.djangoproject.com/documentation/model_api/#managers
-.. _manager documentation: http://www.djangoproject.com/documentation/model_api/#managers
+.. _manager: ../model-api/#managers
+.. _manager documentation: ../model-api/#managers
How Django uses the sites framework
===================================
@@ -316,7 +316,7 @@ Here's how Django uses the sites framework:
* The shortcut view (``django.views.defaults.shortcut``) uses the domain of
the current ``Site`` object when calculating an object's URL.
-.. _redirects framework: http://www.djangoproject.com/documentation/redirects/
-.. _flatpages framework: http://www.djangoproject.com/documentation/flatpages/
-.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
-.. _authentication framework: http://www.djangoproject.com/documentation/authentication/
+.. _redirects framework: ../redirects/
+.. _flatpages framework: ../flatpages/
+.. _syndication framework: ../syndication/
+.. _authentication framework: ../authentication/
diff --git a/docs/static_files.txt b/docs/static_files.txt
index 55380a659b..b6a1d278fd 100644
--- a/docs/static_files.txt
+++ b/docs/static_files.txt
@@ -24,7 +24,7 @@ production setting. Use this only for development.
For information on serving static files in an Apache production environment,
see the `Django mod_python documentation`_.
-.. _Django mod_python documentation: http://www.djangoproject.com/documentation/modpython/#serving-media-files
+.. _Django mod_python documentation: ../modpython/#serving-media-files
How to do it
============
@@ -49,7 +49,7 @@ Examples:
* The file ``/path/bar.jpg`` will not be accessible, because it doesn't
fall under the document root.
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+.. _URLconf: ../url_dispatch/
Directory listings
==================
@@ -122,4 +122,4 @@ associated with the ``django.views.static.serve`` view. If not
Of course, the catch here is that you'll have to remember to set ``DEBUG=False``
in your production settings file. But you should be doing that anyway.
-.. _DEBUG setting: http://www.djangoproject.com/documentation/settings/#debug
+.. _DEBUG setting: ../settings/#debug
diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt
index 59a9022d9b..2a03e6d5a6 100644
--- a/docs/syndication_feeds.txt
+++ b/docs/syndication_feeds.txt
@@ -26,7 +26,7 @@ to determine which feed to output.
To create a feed, just write a ``Feed`` class and point to it in your URLconf_.
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
+.. _URLconf: ../url_dispatch/
Initialization
--------------
@@ -72,8 +72,8 @@ The above example registers two feeds:
Once that's set up, you just need to define the ``Feed`` classes themselves.
-.. _URLconf: http://www.djangoproject.com/documentation/url_dispatch/
-.. _settings file: http://www.djangoproject.com/documentation/settings/
+.. _URLconf: ../url_dispatch/
+.. _settings file: ../settings/
Feed classes
------------
@@ -114,6 +114,9 @@ Note:
`object-relational mapper`_, ``items()`` doesn't have to return model
instances. Although you get a few bits of functionality "for free" by
using Django models, ``items()`` can return any type of object you want.
+ * If you're creating an Atom feed, rather than an RSS feed, set the
+ ``subtitle`` attribute instead of the ``description`` attribute. See
+ `Publishing Atom and RSS feeds in tandem`_, later, for an example.
One thing's left to do. In an RSS feed, each ``<item>`` has a ``<title>``,
``<link>`` and ``<description>``. We need to tell the framework what data to
@@ -127,7 +130,7 @@ put into those elements.
it two template context variables:
* ``{{ obj }}`` -- The current object (one of whichever objects you
- returned in ``items()``).
+ returned in ``items()``).
* ``{{ site }}`` -- A ``django.models.core.sites.Site`` object
representing the current site. This is useful for
``{{ site.domain }}`` or ``{{ site.name }}``.
@@ -143,7 +146,10 @@ put into those elements.
exist, it tries calling a method ``item_link()`` in the ``Feed`` class,
passing it a single parameter, ``item``, which is the object itself.
Both ``get_absolute_url()`` and ``item_link()`` should return the item's
- URL as a normal Python string.
+ URL as a normal Python string. As with ``get_absolute_url()``, the
+ result of ``item_link()`` will be included directly in the URL, so you
+ are responsible for doing all necessary URL quoting and conversion to
+ ASCII inside the method itself.
* For the LatestEntries example above, we could have very simple feed templates:
@@ -156,8 +162,8 @@ put into those elements.
{{ obj.description }}
.. _chicagocrime.org: http://www.chicagocrime.org/
-.. _object-relational mapper: http://www.djangoproject.com/documentation/db_api/
-.. _Django templates: http://www.djangoproject.com/documentation/templates/
+.. _object-relational mapper: ../db-api/
+.. _Django templates: ../templates/
A complex example
-----------------
@@ -277,7 +283,7 @@ Feeds created by the syndication framework automatically include the
appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This
comes directly from your `LANGUAGE_CODE setting`_.
-.. _LANGUAGE_CODE setting: http://www.djangoproject.com/documentation/settings/#language-code
+.. _LANGUAGE_CODE setting: ../settings/#language-code
URLs
----
@@ -292,13 +298,13 @@ Atom feeds require a ``<link rel="self">`` that defines the feed's current
location. The syndication framework populates this automatically, using the
domain of the current site according to the SITE_ID setting.
-.. _SITE_ID setting: http://www.djangoproject.com/documentation/settings/#site-id
+.. _SITE_ID setting: ../settings/#site-id
Publishing Atom and RSS feeds in tandem
---------------------------------------
Some developers like to make available both Atom *and* RSS versions of their
-feeds. That's easy to do with Django: Just create a subclass of your ``feed``
+feeds. That's easy to do with Django: Just create a subclass of your ``Feed``
class and set the ``feed_type`` to something different. Then update your
URLconf to add the extra versions.
@@ -318,6 +324,20 @@ Here's a full example::
class AtomSiteNewsFeed(RssSiteNewsFeed):
feed_type = Atom1Feed
+ subtitle = RssSiteNewsFeed.description
+
+.. Note::
+ In this example, the RSS feed uses a ``description`` while the Atom feed
+ uses a ``subtitle``. That's because Atom feeds don't provide for a
+ feed-level "description," but they *do* provide for a "subtitle."
+
+ If you provide a ``description`` in your ``Feed`` class, Django will *not*
+ automatically put that into the ``subtitle`` element, because a subtitle
+ and description are not necessarily the same thing. Instead, you should
+ define a ``subtitle`` attribute.
+
+ In the above example, we simply set the Atom feed's ``subtitle`` to the
+ RSS feed's ``description``, because it's quite short already.
And the accompanying URLconf::
@@ -478,6 +498,22 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
categories = ("python", "django") # Hard-coded list of categories.
+ # COPYRIGHT NOTICE -- One of the following three is optional. The
+ # framework looks for them in this order.
+
+ def copyright(self, obj):
+ """
+ Takes the object returned by get_object() and returns the feed's
+ copyright notice as a normal Python string.
+ """
+
+ def copyright(self):
+ """
+ Returns the feed's copyright notice as a normal Python string.
+ """
+
+ copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
+
# ITEMS -- One of the following three is required. The framework looks
# for them in this order.
@@ -613,15 +649,15 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
def item_enclosure_mime_type(self, item):
"""
Takes an item, as returned by items(), and returns the item's
- enclosure mime type.
+ enclosure MIME type.
"""
def item_enclosure_mime_type(self):
"""
- Returns the enclosure length, in bytes, for every item in the feed.
+ Returns the enclosure MIME type for every item in the feed.
"""
- item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure mime-type.
+ item_enclosure_mime_type = "audio/mpeg" # Hard-coded enclosure MIME type.
# ITEM PUBDATE -- It's optional to use one of these three. This is a
# hook that specifies how to get the pubdate for a given item.
@@ -659,6 +695,23 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas
item_categories = ("python", "django") # Hard-coded categories.
+ # ITEM COPYRIGHT NOTICE (only applicable to Atom feeds) -- One of the
+ # following three is optional. The framework looks for them in this
+ # order.
+
+ def item_copyright(self, obj):
+ """
+ Takes an item, as returned by items(), and returns the item's
+ copyright notice as a normal Python string.
+ """
+
+ def item_copyright(self):
+ """
+ Returns the copyright notice for every item in the feed.
+ """
+
+ item_copyright = 'Copyright (c) 2007, Sally Smith' # Hard-coded copyright notice.
+
The low-level framework
=======================
diff --git a/docs/templates.txt b/docs/templates.txt
index b4cc47b9f3..cb8e238f43 100644
--- a/docs/templates.txt
+++ b/docs/templates.txt
@@ -91,9 +91,12 @@ Filters can be "chained." The output of one filter is applied to the next.
``{{ text|escape|linebreaks }}`` is a common idiom for escaping text contents,
then converting line breaks to ``<p>`` tags.
-Some filters take arguments. A filter argument looks like this:
-``{{ bio|truncatewords:"30" }}``. This will display the first 30 words of the
-``bio`` variable. Filter arguments always are in double quotes.
+Some filters take arguments. A filter argument looks like this: ``{{
+bio|truncatewords:30 }}``. This will display the first 30 words of the ``bio``
+variable.
+
+Filter arguments that contain spaces must be quoted; for example, to join a list
+with commas and spaced you'd use ``{{ list|join:", " }}``.
The `Built-in filter reference`_ below describes all the built-in filters.
@@ -112,9 +115,7 @@ know how to write Python code.
Comments
========
-**New in Django development version**
-
-To comment-out part of a template, use the comment syntax: ``{# #}``.
+To comment-out part of a line in a template, use the comment syntax: ``{# #}``.
For example, this template would render as ``'hello'``::
@@ -124,6 +125,12 @@ A comment can contain any template code, invalid or not. For example::
{# {% if foo %}bar{% else %} #}
+This syntax can only be used for single-line comments (no newlines are
+permitted between the ``{#`` and ``#}`` delimiters). If you need to comment
+out a multiline portion of the template, see the ``comment`` tag, below__.
+
+__ comment_
+
Template inheritance
====================
@@ -253,6 +260,16 @@ Here are some tips for working with inheritance:
if you want to add to the contents of a parent block instead of
completely overriding it.
+ * For extra readability, you can optionally give a *name* to your
+ ``{% endblock %}`` tag. For example::
+
+ {% block content %}
+ ...
+ {% endblock content %}
+
+ In larger templates, this technique helps you see which ``{% block %}``
+ tags are being closed.
+
Finally, note that you can't define multiple ``{% block %}`` tags with the same
name in the same template. This limitation exists because a block tag works in
"both" directions. That is, a block tag doesn't just provide a hole to fill --
@@ -430,7 +447,7 @@ for
~~~
Loop over each item in an array. For example, to display a list of athletes
-given ``athlete_list``::
+provided in ``athlete_list``::
<ul>
{% for athlete in athlete_list %}
@@ -438,7 +455,25 @@ given ``athlete_list``::
{% endfor %}
</ul>
-You can also loop over a list in reverse by using ``{% for obj in list reversed %}``.
+You can loop over a list in reverse by using ``{% for obj in list reversed %}``.
+
+**New in Django development version**
+If you need to loop over a list of lists, you can unpack the values
+in eachs sub-list into a set of known names. For example, if your context contains
+a list of (x,y) coordinates called ``points``, you could use the following
+to output the list of points::
+
+ {% for x, y in points %}
+ There is a point at {{ x }},{{ y }}
+ {% endfor %}
+
+This can also be useful if you need to access the items in a dictionary.
+For example, if your context contained a dictionary ``data``, the following
+would display the keys and values of the dictionary::
+
+ {% for key, value in data.items %}
+ {{ key }}: {{ value }}
+ {% endfor %}
The for loop sets a number of variables available within the loop:
@@ -538,9 +573,9 @@ The 'ifchanged' block tag is used within a loop. It has two possible uses.
<a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a>
{% endfor %}
-2. **New in Django development version.** If given a variable, check whether that
- variable has changed. For example, the following shows the date every time it
- changes, but only shows the hour if both the hour and the date has changed::
+2. If given a variable, check whether that variable has changed. For
+ example, the following shows the date every time it changes, but
+ only shows the hour if both the hour and the date has changed::
{% for date in days %}
{% ifchanged date.date %} {{ date.date }} {% endifchanged %}
@@ -635,6 +670,7 @@ Available format strings:
output, because this includes periods
to match Associated Press style.)
A ``'AM'`` or ``'PM'``. ``'AM'``
+ b Month, textual, 3 letters, lowercase. ``'jan'``
B Not implemented.
d Day of the month, 2 digits with ``'01'`` to ``'31'``
leading zeros.
@@ -693,11 +729,11 @@ Example::
Note that you can backslash-escape a format string if you want to use the
"raw" value. In this example, "f" is backslash-escaped, because otherwise
"f" is a format string that displays the time. The "o" doesn't need to be
-escaped, because it's not a format character.::
+escaped, because it's not a format character::
It is the {% now "jS o\f F" %}
-(Displays "It is the 4th of September" %}
+This would display as "It is the 4th of September".
regroup
~~~~~~~
@@ -728,6 +764,7 @@ The following snippet of template code would accomplish this dubious task::
<li>{{ item }}</li>
{% endfor %}
</ul>
+ </li>
{% endfor %}
</ul>
@@ -747,7 +784,7 @@ i.e.::
spaceless
~~~~~~~~~
-Normalizes whitespace between HTML tags to a single space. This includes tab
+Removes whitespace between HTML tags. This includes tab
characters and newlines.
Example usage::
@@ -760,9 +797,9 @@ Example usage::
This example would return this HTML::
- <p> <a href="foo/">Foo</a> </p>
+ <p><a href="foo/">Foo</a></p>
-Only space between *tags* is normalized -- not space between tags and text. In
+Only space between *tags* is removed -- not space between tags and text. In
this example, the space around ``Hello`` won't be stripped::
{% spaceless %}
@@ -792,7 +829,7 @@ Note that if you use ``{% ssi %}``, you'll need to define
See also: ``{% include %}``.
-.. _ALLOWED_INCLUDE_ROOTS: http://www.djangoproject.com/documentation/settings/#allowed-include-roots
+.. _ALLOWED_INCLUDE_ROOTS: ../settings/#allowed-include-roots
templatetag
~~~~~~~~~~~
@@ -817,7 +854,38 @@ The argument tells which template bit to output:
``closecomment`` ``#}``
================== =======
-Note: ``opencomment`` and ``closecomment`` are new in the Django development version.
+url
+~~~
+
+**Note that the syntax for this tag may change in the future, as we make it more robust.**
+
+Returns an absolute URL (i.e., a URL without the domain name) matching a given
+view function and optional parameters. This is a way to output links without
+violating the DRY principle by having to hard-code URLs in your templates::
+
+ {% url path.to.some_view arg1,arg2,name1=value1 %}
+
+The first argument is a path to a view function in the format
+``package.package.module.function``. Additional arguments are optional and
+should be comma-separated values that will be used as positional and keyword
+arguments in the URL. All arguments required by the URLconf should be present.
+
+For example, suppose you have a view, ``app_views.client``, whose URLconf
+takes a client ID (here, ``client()`` is a method inside the views file
+``app_views.py``). The URLconf line might look like this::
+
+ ('^client/(\d+)/$', 'app_views.client')
+
+If this app's URLconf is included into the project's URLconf under a path
+such as this::
+
+ ('^clients/', include('project_name.app_name.urls'))
+
+...then, in a template, you can create a link to this view like this::
+
+ {% url app_views.client client.id %}
+
+The template tag will output the string ``/clients/client/123/``.
widthratio
~~~~~~~~~~
@@ -833,6 +901,23 @@ Above, if ``this_value`` is 175 and ``max_value`` is 200, the the image in the
above example will be 88 pixels wide (because 175/200 = .875; .875 * 100 = 87.5
which is rounded up to 88).
+with
+~~~~
+
+**New in Django development version**
+
+Caches a complex variable under a simpler name. This is useful when accessing
+an "expensive" method (e.g., one that hits the database) multiple times.
+
+For example::
+
+ {% with business.employees.count as total %}
+ {{ total }} employee{{ total|pluralize }}
+ {% endwith %}
+
+The populated variable (in the example above, ``total``) is only available
+between the ``{% with %}`` and ``{% endwith %}`` tags.
+
Built-in filter reference
-------------------------
@@ -924,13 +1009,29 @@ Replaces ampersands with ``&amp;`` entities.
floatformat
~~~~~~~~~~~
-Rounds a floating-point number to one decimal place -- but only if there's a
-decimal part to be displayed. For example:
+When used without an argument, rounds a floating-point number to one decimal
+place -- but only if there's a decimal part to be displayed. For example:
* ``36.123`` gets converted to ``36.1``
* ``36.15`` gets converted to ``36.2``
* ``36`` gets converted to ``36``
+If used with a numeric integer argument, ``floatformat`` rounds a number to that
+many decimal places. For example:
+
+ * ``36.1234`` with floatformat:3 gets converted to ``36.123``
+ * ``36`` with floatformat:4 gets converted to ``36.0000``
+
+If the argument passed to ``floatformat`` is negative, it will round a number to
+that many decimal places -- but only if there's a decimal part to be displayed.
+For example:
+
+ * ``36.1234`` with floatformat:-3 gets converted to ``36.123``
+ * ``36`` with floatformat:-4 gets converted to ``36``
+
+Using ``floatformat`` with no argument is equivalent to using ``floatformat`` with
+an argument of ``-1``.
+
get_digit
~~~~~~~~~
@@ -1115,6 +1216,16 @@ Truncates a string after a certain number of words.
**Argument:** Number of words to truncate after
+truncatewords_html
+~~~~~~~~~~~~~~~~~~
+
+Similar to ``truncatewords``, except that it is aware of HTML tags. Any tags
+that are opened in the string and not closed before the truncation point, are
+closed immediately after the truncation.
+
+This is less efficient than ``truncatewords``, so should only be used when it
+is being passed HTML text.
+
unordered_list
~~~~~~~~~~~~~~
@@ -1200,7 +1311,7 @@ django.contrib.humanize
A set of Django template filters useful for adding a "human touch" to data. See
the `humanize documentation`_.
-.. _humanize documentation: http://www.djangoproject.com/documentation/add_ons/#humanize
+.. _humanize documentation: ../add_ons/#humanize
django.contrib.markup
---------------------
@@ -1210,3 +1321,11 @@ A collection of template filters that implement these common markup languages:
* Textile
* Markdown
* ReST (ReStructured Text)
+
+django.contrib.webdesign
+------------------------
+
+A collection of template tags that can be useful while designing a website,
+such as a generator of Lorem Ipsum text. See the `webdesign documentation`_.
+
+.. _webdesign documentation: ../webdesign/
diff --git a/docs/templates_python.txt b/docs/templates_python.txt
index 7aeed935b9..c967df1a49 100644
--- a/docs/templates_python.txt
+++ b/docs/templates_python.txt
@@ -11,7 +11,7 @@ If you're looking to use the Django template system as part of another
application -- i.e., without the rest of the framework -- make sure to read
the `configuration`_ section later in this document.
-.. _`The Django template language: For template authors`: http://www.djangoproject.com/documentation/templates/
+.. _`The Django template language: For template authors`: ../templates/
Basics
======
@@ -212,21 +212,24 @@ template tags. If an invalid variable is provided to one of these template
tags, the variable will be interpreted as ``None``. Filters are always
applied to invalid variables within these template tags.
+If ``TEMPLATE_STRING_IF_INVALID`` contains a ``'%s'``, the format marker will
+be replaced with the name of the invalid variable.
+
.. admonition:: For debug purposes only!
- While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
- it is a bad idea to turn it on as a 'development default'.
-
- Many templates, including those in the Admin site, rely upon the
- silence of the template system when a non-existent variable is
+ While ``TEMPLATE_STRING_IF_INVALID`` can be a useful debugging tool,
+ it is a bad idea to turn it on as a 'development default'.
+
+ Many templates, including those in the Admin site, rely upon the
+ silence of the template system when a non-existent variable is
encountered. If you assign a value other than ``''`` to
- ``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
+ ``TEMPLATE_STRING_IF_INVALID``, you will experience rendering
problems with these templates and sites.
-
- Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
- in order to debug a specific template problem, then cleared
+
+ Generally, ``TEMPLATE_STRING_IF_INVALID`` should only be enabled
+ in order to debug a specific template problem, then cleared
once debugging is complete.
-
+
Playing with Context objects
----------------------------
@@ -291,7 +294,8 @@ return a dictionary of items to be merged into the context. By default,
("django.core.context_processors.auth",
"django.core.context_processors.debug",
- "django.core.context_processors.i18n")
+ "django.core.context_processors.i18n",
+ "django.core.context_processors.media")
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
@@ -327,8 +331,8 @@ Note::
Here's what each of the default processors does:
-.. _HttpRequest object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
-.. _TEMPLATE_CONTEXT_PROCESSORS setting: http://www.djangoproject.com/documentation/settings/#template-context-processors
+.. _HttpRequest object: ../request_response/#httprequest-objects
+.. _TEMPLATE_CONTEXT_PROCESSORS setting: ../settings/#template-context-processors
django.core.context_processors.auth
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -345,7 +349,7 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
``request.user.get_and_delete_messages()`` for every request. That method
collects the user's messages and deletes them from the database.
- Note that messages are set with ``user.add_message()``. See the
+ Note that messages are set with ``user.message_set.create``. See the
`message docs`_ for more.
* ``perms`` -- An instance of
@@ -353,9 +357,9 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
permissions that the currently logged-in user has. See the `permissions
docs`_.
-.. _user authentication docs: http://www.djangoproject.com/documentation/authentication/#users
-.. _message docs: http://www.djangoproject.com/documentation/authentication/#messages
-.. _permissions docs: http://www.djangoproject.com/documentation/authentication/#permissions
+.. _user authentication docs: ../authentication/#users
+.. _message docs: ../authentication/#messages
+.. _permissions docs: ../authentication/#permissions
django.core.context_processors.debug
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -383,9 +387,18 @@ If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
See the `internationalization docs`_ for more.
-.. _LANGUAGES setting: http://www.djangoproject.com/documentation/settings/#languages
-.. _LANGUAGE_CODE setting: http://www.djangoproject.com/documentation/settings/#language-code
-.. _internationalization docs: http://www.djangoproject.com/documentation/i18n/
+.. _LANGUAGES setting: ../settings/#languages
+.. _LANGUAGE_CODE setting: ../settings/#language-code
+.. _internationalization docs: ../i18n/
+
+django.core.context_processors.media
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If ``TEMPLATE_CONTEXT_PROCESSORS`` contains this processor, every
+``RequestContext`` will contain a variable ``MEDIA_URL``, providing the
+value of the `MEDIA_URL setting`_.
+
+.. _MEDIA_URL setting: ../settings/#media-url
django.core.context_processors.request
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -654,6 +667,18 @@ decorator instead::
If you leave off the ``name`` argument, as in the second example above, Django
will use the function's name as the filter name.
+Template filters which expect strings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+If you are writing a template filter which only expects a string as the first
+argument, you should use the included decorator ``stringfilter`` which will convert
+an object to it's string value before being passed to your function::
+
+ from django import template
+
+ @template.stringfilter
+ def lower(value):
+ return value.lower()
+
Writing custom template tags
----------------------------
@@ -668,14 +693,15 @@ how the compilation works and how the rendering works.
When Django compiles a template, it splits the raw template text into
''nodes''. Each node is an instance of ``django.template.Node`` and has
-a ``render()`` method. A compiled template is, simply, a list of ``Node``
-objects. When you call ``render()`` on a compiled template object, the template
-calls ``render()`` on each ``Node`` in its node list, with the given context.
-The results are all concatenated together to form the output of the template.
+either a ``render()`` or ``iter_render()`` method. A compiled template is,
+simply, a list of ``Node`` objects. When you call ``render()`` on a compiled
+template object, the template calls ``render()`` on each ``Node`` in its node
+list, with the given context. The results are all concatenated together to
+form the output of the template.
Thus, to define a custom template tag, you specify how the raw template tag is
converted into a ``Node`` (the compilation function), and what the node's
-``render()`` method does.
+``render()`` or ``iter_render()`` method does.
Writing the compilation function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -702,7 +728,7 @@ object::
# split_contents() knows not to split quoted strings.
tag_name, format_string = token.split_contents()
except ValueError:
- raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents[0]
+ raise template.TemplateSyntaxError, "%r tag requires a single argument" % token.contents.split()[0]
if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
return CurrentTimeNode(format_string[1:-1])
@@ -745,7 +771,8 @@ Writing the renderer
~~~~~~~~~~~~~~~~~~~~
The second step in writing custom tags is to define a ``Node`` subclass that
-has a ``render()`` method.
+has a ``render()`` method (we will discuss the ``iter_render()`` alternative
+in `Improving rendering speed`_, below).
Continuing the above example, we need to define ``CurrentTimeNode``::
@@ -801,6 +828,70 @@ Python 2.4 and above::
If you leave off the ``name`` argument, as in the second example above, Django
will use the function's name as the tag name.
+Passing template variables to the tag
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Although you can pass any number of arguments to a template tag using
+``token.split_contents()``, the arguments are all unpacked as
+string literals. A little more work is required in order to dynamic content (a
+template variable) to a template tag as an argument.
+
+While the previous examples have formatted the current time into a string and
+returned the string, suppose you wanted to pass in a ``DateTimeField`` from an
+object and have the template tag format that date-time::
+
+ <p>This post was last updated at {% format_time blog_entry.date_updated "%Y-%m-%d %I:%M %p" %}.</p>
+
+Initially, ``token.split_contents()`` will return three values:
+
+ 1. The tag name ``format_time``.
+ 2. The string "blog_entry.date_updated" (without the surrounding quotes).
+ 3. The formatting string "%Y-%m-%d %I:%M %p". The return value from
+ ``split_contents()`` will include the leading and trailing quotes for
+ string literals like this.
+
+Now your tag should begin to look like this::
+
+ from django import template
+ def do_format_time(parser, token):
+ try:
+ # split_contents() knows not to split quoted strings.
+ tag_name, date_to_be_formatted, format_string = token.split_contents()
+ except ValueError:
+ raise template.TemplateSyntaxError, "%r tag requires exactly two arguments" % token.contents.split()[0]
+ if not (format_string[0] == format_string[-1] and format_string[0] in ('"', "'")):
+ raise template.TemplateSyntaxError, "%r tag's argument should be in quotes" % tag_name
+ return FormatTimeNode(date_to_be_formatted, format_string[1:-1])
+
+You also have to change the renderer to retrieve the actual contents of the
+``date_updated`` property of the ``blog_entry`` object. This can be
+accomplished by using the ``resolve_variable()`` function in
+``django.template``. You pass ``resolve_variable()`` the variable name and the
+current context, available in the ``render`` method::
+
+ from django import template
+ from django.template import resolve_variable
+ import datetime
+ class FormatTimeNode(template.Node):
+ def __init__(self, date_to_be_formatted, format_string):
+ self.date_to_be_formatted = date_to_be_formatted
+ self.format_string = format_string
+
+ def render(self, context):
+ try:
+ actual_date = resolve_variable(self.date_to_be_formatted, context)
+ return actual_date.strftime(self.format_string)
+ except template.VariableDoesNotExist:
+ return ''
+
+``resolve_variable`` will try to resolve ``blog_entry.date_updated`` and then
+format it accordingly.
+
+.. note::
+ The ``resolve_variable()`` function will throw a ``VariableDoesNotExist``
+ exception if it cannot resolve the string passed to it in the current
+ context of the page.
+
Shortcut for simple tags
~~~~~~~~~~~~~~~~~~~~~~~~
@@ -944,7 +1035,7 @@ The ``takes_context`` parameter defaults to ``False``. When it's set to *True*,
the tag is passed the context object, as in this example. That's the only
difference between this case and the previous ``inclusion_tag`` example.
-.. _tutorials: http://www.djangoproject.com/documentation/tutorial1/#creating-models
+.. _tutorials: ../tutorial01/#creating-models
Setting a variable in the context
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1001,7 +1092,7 @@ class, like so::
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
- raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents[0]
+ raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
m = re.search(r'(.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
@@ -1086,6 +1177,48 @@ For more examples of complex rendering, see the source code for ``{% if %}``,
.. _configuration:
+Improving rendering speed
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+For most practical purposes, the ``render()`` method on a ``Node`` will be
+sufficient and the simplest way to implement a new tag. However, if your
+template tag is expected to produce large strings via ``render()``, you can
+speed up the rendering process (and reduce memory usage) using iterative
+rendering via the ``iter_render()`` method.
+
+The ``iter_render()`` method should either be an iterator that yields string
+chunks, one at a time, or a method that returns a sequence of string chunks.
+The template renderer will join the successive chunks together when creating
+the final output. The improvement over the ``render()`` method here is that
+you do not need to create one large string containing all the output of the
+``Node``, instead you can produce the output in smaller chunks.
+
+By way of example, here's a trivial ``Node`` subclass that simply returns the
+contents of a file it is given::
+
+ class FileNode(Node):
+ def __init__(self, filename):
+ self.filename = filename
+
+ def iter_render(self):
+ for line in file(self.filename):
+ yield line
+
+For very large files, the full file contents will never be read entirely into
+memory when this tag is used, which is a useful optimisation.
+
+If you define an ``iter_render()`` method on your ``Node`` subclass, you do
+not need to define a ``render()`` method. The reverse is true as well: the
+default ``Node.iter_render()`` method will call your ``render()`` method if
+necessary. A useful side-effect of this is that you can develop a new tag
+using ``render()`` and producing all the output at once, which is easy to
+debug. Then you can rewrite the method as an iterator, rename it to
+``iter_render()`` and everything will still work.
+
+It is compulsory, however, to define *either* ``render()`` or ``iter_render()``
+in your subclass. If you omit them both, a ``TypeError`` will be raised when
+the code is imported.
+
Configuring the template system in standalone mode
==================================================
@@ -1115,5 +1248,6 @@ settings you wish to specify. You might want to consider setting at least
`settings documentation`_, and any setting starting with *TEMPLATE_*
is of obvious interest.
-.. _settings file: http://www.djangoproject.com/documentation/settings/#using-settings-without-the-django-settings-module-environment-variable
-.. _settings documentation: http://www.djangoproject.com/documentation/settings/
+.. _settings file: ../settings/#using-settings-without-the-django-settings-module-environment-variable
+.. _settings documentation: ../settings/
+
diff --git a/docs/testing.txt b/docs/testing.txt
index a0b8a8a187..50c4ec3046 100644
--- a/docs/testing.txt
+++ b/docs/testing.txt
@@ -2,21 +2,29 @@
Testing Django applications
===========================
-**New in Django development version**.
+Automated testing is an extremely useful bug-killing tool for the modern
+Web developer. You can use a collection of tests -- a **test suite** -- to
+solve, or avoid, a number of problems:
-Automated testing is an extremely useful weapon in the bug-killing arsenal
-of the modern developer. When initially writing code, a test suite can be
-used to validate that code behaves as expected. When refactoring or
-modifying code, tests serve as a guide to ensure that behavior hasn't
-changed unexpectedly as a result of the refactor.
+ * When you're writing new code, you can use tests to validate your code
+ works as expected.
-Testing a web application is a complex task, as there are many
-components of a web application that must be validated and tested. To
-help you test your application, Django provides a test execution
-framework, and range of utilities that can be used to stimulate and
-inspect various facets of a web application.
+ * When you're refactoring or modifying old code, you can use tests to
+ ensure your changes haven't affected your application's behavior
+ unexpectedly.
- This testing framework is currently under development, and may change
+Testing a Web application is a complex task, because a Web application is made
+of several layers of logic -- from HTTP-level request handling, to form
+validation and processing, to template rendering. With Django's test-execution
+framework and assorted utilities, you can simulate requests, insert test data,
+inspect your application's output and generally verify your code is doing what
+it should be doing.
+
+The best part is, it's really easy.
+
+.. admonition:: Note
+
+ This testing framework is currently under development. It may change
slightly before the next official Django release.
(That's *no* excuse not to write tests, though!)
@@ -92,7 +100,7 @@ Writing unittests
Like doctests, Django's unit tests use a standard library module: unittest_.
As with doctests, Django's test runner looks for any unit test cases defined
-in ``models.py``, or in a ``tests.py`` file stored in the application
+in ``models.py``, or in a ``tests.py`` file stored in the application
directory.
An equivalent unittest test case for the above example would look like::
@@ -111,8 +119,8 @@ An equivalent unittest test case for the above example would look like::
self.assertEquals(self.cat.speak(), 'The cat says "meow"')
When you `run your tests`_, the test utility will find all the test cases
-(that is, subclasses of ``unittest.TestCase``) in ``models.py`` and
-``tests.py``, automatically build a test suite out of those test cases,
+(that is, subclasses of ``unittest.TestCase``) in ``models.py`` and
+``tests.py``, automatically build a test suite out of those test cases,
and run that suite.
For more details about ``unittest``, see the `standard library unittest
@@ -139,7 +147,7 @@ doctests or unit tests are right for you.
If you've been using Python for a while, ``doctest`` will probably feel more
"pythonic". It's designed to make writing tests as easy as possible, so
there's no overhead of writing classes or methods; you simply put tests in
-docstrings. This gives the added advantage of given your modules automatic
+docstrings. This gives the added advantage of giving your modules automatic
documentation -- well-written doctests can kill both the documentation and the
testing bird with a single stone.
@@ -164,12 +172,13 @@ in different circumstances.
Testing Tools
=============
-To assist in testing various features of your application, Django provides
+To assist in testing various features of your application, Django provides
tools that can be used to establish tests and test conditions.
* `Test Client`_
-* Fixtures_
-
+* `TestCase`_
+* `E-mail services`_
+
Test Client
-----------
@@ -178,36 +187,30 @@ GET and POST requests on a URL, and observe the response that is received.
This allows you to test that the correct view is executed for a given URL,
and that the view constructs the correct response.
-As the response is generated, the Test Client gathers details on the
+As the response is generated, the Test Client gathers details on the
Template and Context objects that were used to generate the response. These
Templates and Contexts are then provided as part of the response, and can be
used as test conditions.
.. admonition:: Test Client vs Browser Automation?
- The Test Client is not intended as a replacement for Twill_, Selenium_,
- or other browser automation frameworks - it is intended to allow
- testing of the contexts and templates produced by a view,
+ The Test Client is not intended as a replacement for Twill_, Selenium_,
+ or other browser automation frameworks - it is intended to allow
+ testing of the contexts and templates produced by a view,
rather than the HTML rendered to the end-user.
-
+
A comprehensive test suite should use a combination of both: Test Client
- tests to establish that the correct view is being called and that
+ tests to establish that the correct view is being called and that
the view is collecting the correct context data, and Browser Automation
tests to check that user interface behaves as expected.
-
+
.. _Twill: http://twill.idyll.org/
.. _Selenium: http://www.openqa.org/selenium/
-The Test Client is stateful; if a cookie is returned as part of a response,
-that cookie is provided as part of the next request issued to that Client
-instance. Expiry policies for these cookies are not followed; if you want
-a cookie to expire, either delete it manually from ``client.cookies``, or
-create a new Client instance (which will effectively delete all cookies).
-
Making requests
~~~~~~~~~~~~~~~
-Creating an instance of ``Client`` (``django.test.client.Client``) requires
+Creating an instance of ``Client`` (``django.test.client.Client``) requires
no arguments at time of construction. Once constructed, the following methods
can be invoked on the ``Client`` instance.
@@ -220,104 +223,329 @@ can be invoked on the ``Client`` instance.
will result in the evaluation of a GET request equivalent to::
- http://yoursite.com/customers/details/?name='fred'&age=7
+ http://yoursite.com/customers/details/?name=fred&age=7
+
+``post(path, data={}, content_type=MULTIPART_CONTENT)``
+ Make a POST request on the provided ``path``. If you provide a content type
+ (e.g., ``text/xml`` for an XML payload), the contents of ``data`` will be
+ sent as-is in the POST request, using the content type in the HTTP
+ ``Content-Type`` header.
-``post(path, data={})``
- Make a POST request on the provided ``path``. The key-value pairs in the
- data dictionary will be used to create the POST data payload. This payload
- will be transmitted with the mimetype ``multipart/form-data``.
+ If you do not provide a value for ``content_type``, the values in
+ ``data`` will be transmitted with a content type of ``multipart/form-data``.
+ The key-value pairs in the data dictionary will be encoded as a multipart
+ message and used to create the POST data payload.
- However submitting files is a special case. To POST a file, you need only
- provide the file field name as a key, and a file handle to the file you wish to
- upload as a value. The Test Client will populate the two POST fields (i.e.,
- ``field`` and ``field_file``) required by FileField. For example::
+ To submit multiple values for a given key (for example, to specify
+ the selections for a multiple selection list), provide the values as a
+ list or tuple for the required key. For example, a data dictionary of
+ ``{'choices': ('a','b','d')}`` would submit three selected rows for the
+ field named ``choices``.
+
+ Submitting files is a special case. To POST a file, you need only
+ provide the file field name as a key, and a file handle to the file you wish to
+ upload as a value. The Test Client will populate the two POST fields (i.e.,
+ ``field`` and ``field_file``) required by Django's FileField. For example::
c = Client()
f = open('wishlist.doc')
c.post('/customers/wishes/', {'name':'fred', 'attachment':f})
f.close()
- will result in the evaluation of a POST request on ``/customers/wishes/``,
- with a POST dictionary that contains `name`, `attachment` (containing the
+ will result in the evaluation of a POST request on ``/customers/wishes/``,
+ with a POST dictionary that contains `name`, `attachment` (containing the
file name), and `attachment_file` (containing the file data). Note that you
need to manually close the file after it has been provided to the POST.
-``login(path, username, password)``
- In a production site, it is likely that some views will be protected with
- the @login_required URL provided by ``django.contrib.auth``. Interacting
- with a URL that has been login protected is a slightly complex operation,
- so the Test Client provides a simple URL to automate the login process. A
- call to ``login()`` stimulates the series of GET and POST calls required
- to log a user into a @login_required protected URL.
+``login(**credentials)``
+ **New in Django development version**
- If login is possible, the final return value of ``login()`` is the response
- that is generated by issuing a GET request on the protected URL. If login
- is not possible, ``login()`` returns False.
+ On a production site, it is likely that some views will be protected from
+ anonymous access through the use of the @login_required decorator, or some
+ other login checking mechanism. The ``login()`` method can be used to
+ simulate the effect of a user logging into the site. As a result of calling
+ this method, the Client will have all the cookies and session data required
+ to pass any login-based tests that may form part of a view.
- Note that since the test suite will be executed using the test database,
- which contains no users by default. As a result, logins for your production
- site will not work. You will need to create users as part of the test suite
- to be able to test logins to your application.
+ In most cases, the ``credentials`` required by this method are the username
+ and password of the user that wants to log in, provided as keyword
+ arguments::
+
+ c = Client()
+ c.login(username='fred', password='secret')
+ # Now you can access a login protected view
+
+ If you are using a different authentication backend, this method may
+ require different credentials.
+
+ ``login()`` returns ``True`` if it the credentials were accepted and login
+ was successful.
+
+ Note that since the test suite will be executed using the test database,
+ which contains no users by default. As a result, logins that are valid
+ on your production site will not work under test conditions. You will
+ need to create users as part of the test suite (either manually, or
+ using a test fixture).
Testing Responses
~~~~~~~~~~~~~~~~~
-The ``get()``, ``post()`` and ``login()`` methods all return a Response
-object. This Response object has the following properties that can be used
-for testing purposes:
+The ``get()`` and ``post()`` methods both return a Response object. This
+Response object has the following properties that can be used for testing
+purposes:
=============== ==========================================================
Property Description
=============== ==========================================================
- ``status_code`` The HTTP status of the response. See RFC2616_ for a
+ ``status_code`` The HTTP status of the response. See RFC2616_ for a
full list of HTTP status codes.
- ``content`` The body of the response. The is the final page
- content as rendered by the view, or any error message
+ ``content`` The body of the response. This is the final page
+ content as rendered by the view, or any error message
(such as the URL for a 302 redirect).
- ``template`` The Template instance that was used to render the final
- content. Testing ``template.name`` can be particularly
- useful; if the template was loaded from a file,
- ``template.name`` will be the file name that was loaded.
+ ``template`` The Template instance that was used to render the final
+ content. Testing ``template.name`` can be particularly
+ useful; if the template was loaded from a file,
+ ``template.name`` will be the file name that was loaded.
- If multiple templates were rendered, (e.g., if one
- template includes another template),``template`` will
- be a list of Template objects, in the order in which
+ If multiple templates were rendered, (e.g., if one
+ template includes another template),``template`` will
+ be a list of Template objects, in the order in which
they were rendered.
- ``context`` The Context that was used to render the template that
+ ``context`` The Context that was used to render the template that
produced the response content.
- As with ``template``, if multiple templates were rendered
- ``context`` will be a list of Context objects, stored in
- the order in which they were rendered.
+ As with ``template``, if multiple templates were rendered
+ ``context`` will be a list of Context objects, stored in
+ the order in which they were rendered.
=============== ==========================================================
.. _RFC2616: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+Exceptions
+~~~~~~~~~~
+
+If you point the Test Client at a view that raises an exception, that exception
+will be visible in the test case. You can then use a standard ``try...catch``
+block, or ``unittest.TestCase.assertRaises()`` to test for exceptions.
+
+The only exceptions that are not visible in a Test Case are ``Http404``,
+``PermissionDenied`` and ``SystemExit``. Django catches these exceptions
+internally and converts them into the appropriate HTTP responses codes.
+
+Persistent state
+~~~~~~~~~~~~~~~~
+
+The Test Client is stateful; if a cookie is returned as part of a response,
+that cookie is provided as part of the next request issued by that Client
+instance. Expiry policies for these cookies are not followed; if you want
+a cookie to expire, either delete it manually or create a new Client
+instance (which will effectively delete all cookies).
+
+There are two properties of the Test Client which are used to store persistent
+state information. If necessary, these properties can be interrogated as
+part of a test condition.
+
+ =============== ==========================================================
+ Property Description
+ =============== ==========================================================
+ ``cookies`` A Python ``SimpleCookie`` object, containing the current
+ values of all the client cookies.
+
+ ``session`` A dictionary-like object containing session information.
+ See the `session documentation`_ for full details.
+ =============== ==========================================================
+
+.. _`session documentation`: ../sessions/
+
+Example
+~~~~~~~
+
The following is a simple unit test using the Test Client::
-
+
import unittest
from django.test.client import Client
-
+
class SimpleTest(unittest.TestCase):
def setUp(self):
# Every test needs a client
self.client = Client()
- def test_details(self):
+ def test_details(self):
# Issue a GET request
response = self.client.get('/customer/details/')
-
+
# Check that the respose is 200 OK
self.failUnlessEqual(response.status_code, 200)
# Check that the rendered context contains 5 customers
self.failUnlessEqual(len(response.context['customers']), 5)
-Fixtures
+TestCase
--------
-Feature still to come...
+Normal python unit tests extend a base class of ``unittest.testCase``.
+Django provides an extension of this base class - ``django.test.TestCase``
+- that provides some additional capabilities that can be useful for
+testing web sites.
+
+Moving from a normal unittest TestCase to a Django TestCase is easy - just
+change the base class of your test from ``unittest.TestCase`` to
+``django.test.TestCase``. All of the standard Python unit test facilities
+will continue to be available, but they will be augmented with some useful
+extra facilities.
+
+Default Test Client
+~~~~~~~~~~~~~~~~~~~
+**New in Django development version**
+
+Every test case in a ``django.test.TestCase`` instance has access to an
+instance of a Django `Test Client`_. This Client can be accessed as
+``self.client``. This client is recreated for each test.
+
+Fixture loading
+~~~~~~~~~~~~~~~
+
+A test case for a database-backed website isn't much use if there isn't any
+data in the database. To make it easy to put test data into the database,
+Django provides a fixtures framework.
+
+A *Fixture* is a collection of files that contain the serialized contents of
+the database. Each fixture has a unique name; however, the files that
+comprise the fixture can be distributed over multiple directories, in
+multiple applications.
+
+.. note::
+ If you have synchronized a Django project, you have already experienced
+ the use of one fixture -- the ``initial_data`` fixture. Every time you
+ synchronize the database, Django installs the ``initial_data`` fixture.
+ This provides a mechanism to populate a new database with any initial
+ data (such as a default set of categories). Fixtures with other names
+ can be installed manually using ``django-admin.py loaddata``.
+
+However, for the purposes of unit testing, each test must be able to
+guarantee the contents of the database at the start of each and every
+test.
+
+To define a fixture for a test, all you need to do is add a class
+attribute to your test describing the fixtures you want the test to use.
+For example, the test case from `Writing unittests`_ would
+look like::
+
+ from django.test import TestCase
+ from myapp.models import Animal
+
+ class AnimalTestCase(TestCase):
+ fixtures = ['mammals.json', 'birds']
+
+ def setUp(self):
+ # test definitions as before
+
+At the start of each test case, before ``setUp()`` is run, Django will
+flush the database, returning the database the state it was in directly
+after ``syncdb`` was called. Then, all the named fixtures are installed.
+In this example, any JSON fixture called ``mammals``, and any fixture
+named ``birds`` will be installed. See the documentation on
+`loading fixtures`_ for more details on defining and installing fixtures.
+
+.. _`loading fixtures`: ../django-admin/#loaddata-fixture-fixture
+
+This flush/load procedure is repeated for each test in the test case, so you
+can be certain that the outcome of a test will not be affected by
+another test, or the order of test execution.
+
+Emptying the test outbox
+~~~~~~~~~~~~~~~~~~~~~~~~
+**New in Django development version**
+
+At the start of each test case, in addition to installing fixtures,
+Django clears the contents of the test e-mail outbox.
+
+For more detail on e-mail services during tests, see `E-mail services`_.
+
+Assertions
+~~~~~~~~~~
+**New in Django development version**
+
+Normal Python unit tests have a wide range of assertions, such as
+``assertTrue`` and ``assertEquals`` that can be used to validate behavior.
+``django.TestCase`` adds to these, providing some assertions
+that can be useful in testing the behavior of web sites.
+
+``assertContains(response, text, count=1, status_code=200)``
+ Assert that a response indicates that a page could be retrieved and
+ produced the nominated status code, and that ``text`` occurs ``count``
+ times in the content of the response.
+
+``assertFormError(response, form, field, errors)``
+ Assert that a field on a form raised the provided list of errors when
+ rendered on the form.
+
+ ``form`` is the name the form object was given in the template context.
+
+ ``field`` is the name of the field on the form to check. If ``field``
+ has a value of ``None``, non-field errors will be checked.
+
+ ``errors`` is an error string, or a list of error strings, that are
+ expected as a result of form validation.
+
+``assertTemplateNotUsed(response, template_name)``
+ Assert that the template with the given name was *not* used in rendering
+ the response.
+
+``assertRedirects(response, expected_path, status_code=302, target_status_code=200)``
+ Assert that the response received produced the nominated status code,
+ redirects the browser to the provided path, and that retrieving the provided
+ path yields a response with the target status code.
+
+``assertTemplateUsed(response, template_name)``
+ Assert that the template with the given name was used in rendering the
+ response.
+
+E-mail services
+---------------
+
+**New in Django development version**
+
+If your view makes use of the `Django e-mail services`_, you don't really
+want e-mail to be sent every time you run a test using that view.
+
+When the Django test framework is initialized, it transparently replaces the
+normal `SMTPConnection`_ class with a dummy implementation that redirects all
+e-mail to a dummy outbox. This outbox, stored as ``django.core.mail.outbox``,
+is a simple list of all `EmailMessage`_ instances that have been sent.
+For example, during test conditions, it would be possible to run the following
+code::
+
+ from django.core import mail
+
+ # Send message
+ mail.send_mail('Subject here', 'Here is the message.', 'from@example.com',
+ ['to@example.com'], fail_silently=False)
+
+ # One message has been sent
+ self.assertEqual(len(mail.outbox), 1)
+ # Subject of first message is correct
+ self.assertEqual(mail.outbox[0].subject, 'Subject here')
+
+The ``mail.outbox`` object does not exist under normal execution conditions.
+The outbox is created during test setup, along with the dummy `SMTPConnection`_.
+When the test framework is torn down, the standard `SMTPConnection`_ class
+is restored, and the test outbox is destroyed.
+
+As noted `previously`_, the test outbox is emptied at the start of every
+test in a Django TestCase. To empty the outbox manually, assign the empty list
+to mail.outbox::
+
+ from django.core import mail
+
+ # Empty the test outbox
+ mail.outbox = []
+
+.. _`Django e-mail services`: ../email/
+.. _`SMTPConnection`: ../email/#the-emailmessage-and-smtpconnection-classes
+.. _`EmailMessage`: ../email/#the-emailmessage-and-smtpconnection-classes
+.. _`previously`: #emptying-the-test-outbox
Running tests
=============
@@ -335,13 +563,25 @@ but you only want to run the animals unit tests, run::
When you run your tests, you'll see a bunch of text flow by as the test
database is created and models are initialized. This test database is
-created from scratch every time you run your tests.
+created from scratch every time you run your tests.
-By default, the test database gets its name by prepending ``test_`` to
-the database name specified by the ``DATABASE_NAME`` setting; all other
+By default, the test database gets its name by prepending ``test_`` to
+the database name specified by the ``DATABASE_NAME`` setting; all other
database settings will the same as they would be for the project normally.
-If you wish to use a name other than the default for the test database,
-you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
+If you wish to use a name other than the default for the test database,
+you can use the ``TEST_DATABASE_NAME`` setting to provide a name.
+
+**New in Django development version:** For fine-grained control over the
+character encoding of your database, use the ``TEST_DATABASE_CHARSET`` setting.
+If you're using MySQL, you can also use the ``TEST_DATABASE_COLLATION`` setting
+to control the particular collation used by the test database. See the
+settings_ documentation for details of these advanced settings.
+
+.. _settings: ../settings/
+
+The test database is created by the user in the ``DATABASE_USER`` setting.
+This user needs to have sufficient privileges to create a new database on the
+system.
Once the test database has been established, Django will run your tests.
If everything goes well, at the end you'll see::
@@ -377,7 +617,11 @@ failed::
FAILED (failures=1)
-When the tests have all been executed, the test database is destroyed.
+The return code for the script is the total number of failed and erroneous
+tests. If all the tests pass, the return code is 0.
+
+Regardless of whether the tests pass or fail, the test database is destroyed when
+all the tests have been executed.
Using a different testing framework
===================================
@@ -388,7 +632,8 @@ it does provide a mechanism to allow you to invoke tests constructed for
an alternative framework as if they were normal Django tests.
When you run ``./manage.py test``, Django looks at the ``TEST_RUNNER``
-setting to determine what to do. By default, ``TEST_RUNNER`` points to ``django.test.simple.run_tests``. This method defines the default Django
+setting to determine what to do. By default, ``TEST_RUNNER`` points to
+``django.test.simple.run_tests``. This method defines the default Django
testing behavior. This behavior involves:
#. Performing global pre-test setup
@@ -396,7 +641,7 @@ testing behavior. This behavior involves:
#. Running ``syncdb`` to install models and initial data into the test database
#. Looking for Unit Tests and Doctests in ``models.py`` and ``tests.py`` file for each installed application
#. Running the Unit Tests and Doctests that are found
-#. Destroying the test database.
+#. Destroying the test database
#. Performing global post-test teardown
If you define your own test runner method and point ``TEST_RUNNER``
@@ -414,10 +659,12 @@ arguments:
The module list is the list of Python modules that contain the models to be
tested. This is the same format returned by ``django.db.models.get_apps()``
- Verbosity determines the amount of notification and debug information that
- will be printed to the console; '0' is no output, '1' is normal output,
+ Verbosity determines the amount of notification and debug information that
+ will be printed to the console; `0` is no output, `1` is normal output,
and `2` is verbose output.
+ This method should return the number of tests that failed.
+
Testing utilities
-----------------
@@ -425,12 +672,13 @@ To assist in the creation of your own test runner, Django provides
a number of utility methods in the ``django.test.utils`` module.
``setup_test_environment()``
- Performs any global pre-test setup, such as the installing the
- instrumentation of the template rendering system.
+ Performs any global pre-test setup, such as the installing the
+ instrumentation of the template rendering system and setting up
+ the dummy SMTPConnection.
``teardown_test_environment()``
- Performs any global post-test teardown, such as removing the instrumentation
- of the template rendering system.
+ Performs any global post-test teardown, such as removing the instrumentation
+ of the template rendering system and restoring normal e-mail services.
``create_test_db(verbosity=1, autoclobber=False)``
Creates a new test database, and run ``syncdb`` against it.
diff --git a/docs/tutorial01.txt b/docs/tutorial01.txt
index 1113b603da..c40b051b19 100644
--- a/docs/tutorial01.txt
+++ b/docs/tutorial01.txt
@@ -17,7 +17,16 @@ installed by running the Python interactive interpreter and typing
``import django``. If that command runs successfully, with no errors, Django is
installed.
-.. _`Django installed`: http://www.djangoproject.com/documentation/install/
+.. _`Django installed`: ../install/
+
+.. admonition:: Where to get help:
+
+ If you're having trouble going through this tutorial, please post a message
+ to `django-users`_ or drop by `#django`_ on ``irc.freenode.net`` and we'll
+ try to help.
+
+.. _django-users: http://groups.google.com/group/django-users
+.. _#django: irc://irc.freenode.net/django
Creating a project
==================
@@ -32,6 +41,13 @@ From the command line, ``cd`` into a directory where you'd like to store your
code, then run the command ``django-admin.py startproject mysite``. This
will create a ``mysite`` directory in your current directory.
+.. note::
+
+ You'll need to avoid naming projects after built-in Python or Django
+ components. In particular, this means you should avoid using names like
+ ``django`` (which will conflict with Django itself) or ``site`` (which
+ conflicts with a built-in Python package).
+
(``django-admin.py`` should be on your system path if you installed Django via
``python setup.py``. If it's not on your path, you can find it in
``site-packages/django/bin``, where ``site-packages`` is a directory within
@@ -108,7 +124,7 @@ It worked!
Full docs for the development server are at `django-admin documentation`_.
-.. _django-admin documentation: http://www.djangoproject.com/documentation/django_admin/
+.. _django-admin documentation: ../django-admin/
Database setup
--------------
@@ -117,8 +133,8 @@ Now, edit ``settings.py``. It's a normal Python module with module-level
variables representing Django settings. Change these settings to match your
database's connection parameters:
- * ``DATABASE_ENGINE`` -- Either 'postgresql', 'mysql' or 'sqlite3'.
- More coming soon.
+ * ``DATABASE_ENGINE`` -- Either 'postgresql_psycopg2', 'mysql' or 'sqlite3'.
+ Other backends are `also available`_.
* ``DATABASE_NAME`` -- The name of your database, or the full (absolute)
path to the database file if you're using SQLite.
* ``DATABASE_USER`` -- Your database username (not used for SQLite).
@@ -127,6 +143,8 @@ database's connection parameters:
empty string if your database server is on the same physical machine
(not used for SQLite).
+.. _also available: ../settings/
+
.. admonition:: Note
If you're using PostgreSQL or MySQL, make sure you've created a database by
@@ -303,7 +321,8 @@ Now Django knows ``mysite`` includes the ``polls`` app. Let's run another comman
python manage.py sql polls
-You should see the following (the CREATE TABLE SQL statements for the polls app)::
+You should see something similar to the following (the CREATE TABLE SQL statements
+for the polls app)::
BEGIN;
CREATE TABLE "polls_poll" (
@@ -321,6 +340,8 @@ You should see the following (the CREATE TABLE SQL statements for the polls app)
Note the following:
+ * The exact output will vary depending on the database you are using.
+
* Table names are automatically generated by combining the name of the app
(``polls``) and the lowercase name of the model -- ``poll`` and
``choice``. (You can override this behavior.)
@@ -349,8 +370,9 @@ If you're interested, also run the following commands:
* ``python manage.py validate polls`` -- Checks for any errors in the
construction of your models.
- * ``python manage.py sqlinitialdata polls`` -- Outputs any initial data
- required for Django's admin framework and your models.
+ * ``python manage.py sqlcustom polls`` -- Outputs any custom SQL statements
+ (such as table modifications or constraints) that are defined for the
+ application.
* ``python manage.py sqlclear polls`` -- Outputs the necessary ``DROP
TABLE`` statements for this app, according to which tables already exist
@@ -360,7 +382,7 @@ If you're interested, also run the following commands:
statements for this app.
* ``python manage.py sqlall polls`` -- A combination of all the SQL from
- the 'sql', 'sqlinitialdata', and 'sqlindexes' commands.
+ the 'sql', 'sqlcustom', and 'sqlindexes' commands.
Looking at the output of those commands can help you understand what's actually
happening under the hood.
@@ -378,7 +400,7 @@ as you like, and it will only ever create the tables that don't exist.
Read the `django-admin.py documentation`_ for full information on what the
``manage.py`` utility can do.
-.. _django-admin.py documentation: http://www.djangoproject.com/documentation/django_admin/
+.. _django-admin.py documentation: ../django-admin/
Playing with the API
====================
@@ -555,5 +577,5 @@ For full details on the database API, see our `Database API reference`_.
When you're comfortable with the API, read `part 2 of this tutorial`_ to get
Django's automatic admin working.
-.. _Database API reference: http://www.djangoproject.com/documentation/db_api/
-.. _part 2 of this tutorial: http://www.djangoproject.com/documentation/tutorial2/
+.. _Database API reference: ../db-api/
+.. _part 2 of this tutorial: ../tutorial02/
diff --git a/docs/tutorial02.txt b/docs/tutorial02.txt
index f6d4045fa3..99f586b4a1 100644
--- a/docs/tutorial02.txt
+++ b/docs/tutorial02.txt
@@ -5,7 +5,7 @@ Writing your first Django app, part 2
This tutorial begins where `Tutorial 1`_ left off. We're continuing the Web-poll
application and will focus on Django's automatically-generated admin site.
-.. _Tutorial 1: http://www.djangoproject.com/documentation/tutorial1/
+.. _Tutorial 1: ../tutorial01/
.. admonition:: Philosophy
@@ -61,10 +61,10 @@ tutorial, remember?) You should see the Django admin index page:
:alt: Django admin index page
:target: http://media.djangoproject.com/img/doc/tutorial/admin02.png
-By default, you should see two types of editable content: groups and users.
-These are core features Django ships with by default.
+You should see a few other types of editable content, including groups, users
+and sites. These are core features Django ships with by default.
-.. _"I can't log in" questions: http://www.djangoproject.com/documentation/faq/#the-admin-site
+.. _"I can't log in" questions: ../faq/#the-admin-site
Make the poll app modifiable in the admin
=========================================
@@ -320,7 +320,7 @@ method a ``short_description`` attribute::
Let's add another improvement to the Poll change list page: Filters. Add the
-following line to ``Poll.admin``::
+following line to ``Poll.Admin``::
list_filter = ['pub_date']
@@ -402,7 +402,7 @@ Django automatically looks for a ``templates/`` subdirectory within each app
package, for use as a fallback. See the `loader types documentation`_ for full
information.
-.. _loader types documentation: http://www.djangoproject.com/documentation/templates_python/#loader-types
+.. _loader types documentation: ../templates_python/#loader-types
Customize the admin index page
==============================
@@ -433,5 +433,5 @@ general, see the `Django admin CSS guide`_.
When you're comfortable with the admin site, read `part 3 of this tutorial`_ to
start working on public poll views.
-.. _Django admin CSS guide: http://www.djangoproject.com/documentation/admin_css/
-.. _part 3 of this tutorial: http://www.djangoproject.com/documentation/tutorial3/
+.. _Django admin CSS guide: ../admin_css/
+.. _part 3 of this tutorial: ../tutorial03/
diff --git a/docs/tutorial03.txt b/docs/tutorial03.txt
index c4c1b4c546..41febe021d 100644
--- a/docs/tutorial03.txt
+++ b/docs/tutorial03.txt
@@ -5,7 +5,7 @@ Writing your first Django app, part 3
This tutorial begins where `Tutorial 2`_ left off. We're continuing the Web-poll
application and will focus on creating the public interface -- "views."
-.. _Tutorial 2: http://www.djangoproject.com/documentation/tutorial2/
+.. _Tutorial 2: ../tutorial02/
Philosophy
==========
@@ -60,9 +60,10 @@ arguments from the dictionary (an optional third item in the tuple).
For more on ``HTTPRequest`` objects, see the `request and response documentation`_.
For more details on URLconfs, see the `URLconf documentation`_.
-When you ran ``python manage.py startproject mysite`` at the beginning of
+When you ran ``python django-admin.py startproject mysite`` at the beginning of
Tutorial 1, it created a default URLconf in ``mysite/urls.py``. It also
-automatically set your ``ROOT_URLCONF`` setting to point at that file::
+automatically set your ``ROOT_URLCONF`` setting (in ``settings.py``) to point
+at that file::
ROOT_URLCONF = 'mysite.urls'
@@ -117,8 +118,8 @@ time the URLconf module is loaded. They're super fast.
.. _Wikipedia's entry: http://en.wikipedia.org/wiki/Regular_expression
.. _Python documentation: http://www.python.org/doc/current/lib/module-re.html
-.. _request and response documentation: http://www.djangoproject.com/documentation/request_response/
-.. _URLconf documentation: http://www.djangoproject.com/documentation/url_dispatch/
+.. _request and response documentation: ../request_response/
+.. _URLconf documentation: ../url_dispatch/
Write your first view
=====================
@@ -260,8 +261,7 @@ provides a shortcut. Here's the full ``index()`` view, rewritten::
latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
return render_to_response('polls/index.html', {'latest_poll_list': latest_poll_list})
-Note that we no longer need to import ``loader``, ``Context`` or
-``HttpResponse``.
+Note that once we've done this in all these views, we no longer need to import ``loader``, ``Context`` and ``HttpResponse``.
The ``render_to_response()`` function takes a template name as its first
argument and a dictionary as its optional second argument. It returns an
@@ -300,7 +300,7 @@ rewritten::
The ``get_object_or_404()`` function takes a Django model module as its first
argument and an arbitrary number of keyword arguments, which it passes to the
-module's ``get_object()`` function. It raises ``Http404`` if the object doesn't
+module's ``get()`` function. It raises ``Http404`` if the object doesn't
exist.
.. admonition:: Philosophy
@@ -377,7 +377,7 @@ iterable of Choice objects and is suitable for use in the ``{% for %}`` tag.
See the `template guide`_ for full details on how templates work.
-.. _template guide: http://www.djangoproject.com/documentation/templates/
+.. _template guide: ../templates/
Simplifying the URLconfs
========================
@@ -464,4 +464,4 @@ All the poll app cares about is its relative URLs, not its absolute URLs.
When you're comfortable with writing views, read `part 4 of this tutorial`_ to
learn about simple form processing and generic views.
-.. _part 4 of this tutorial: http://www.djangoproject.com/documentation/tutorial4/
+.. _part 4 of this tutorial: ../tutorial04/
diff --git a/docs/tutorial04.txt b/docs/tutorial04.txt
index 49ed649cff..5cc12c445d 100644
--- a/docs/tutorial04.txt
+++ b/docs/tutorial04.txt
@@ -48,6 +48,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
from django.shortcuts import get_object_or_404, render_to_response
from django.http import HttpResponseRedirect
+ from django.core.urlresolvers import reverse
from mysite.polls.models import Choice, Poll
# ...
def vote(request, poll_id):
@@ -66,7 +67,7 @@ So let's create a ``vote()`` function in ``mysite/polls/views.py``::
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
- return HttpResponseRedirect('/polls/%s/results/' % p.id)
+ return HttpResponseRedirect(reverse('mysite.polls.views.results', args=(p.id,)))
This code includes a few things we haven't covered yet in this tutorial:
@@ -86,13 +87,29 @@ This code includes a few things we haven't covered yet in this tutorial:
* After incrementing the choice count, the code returns an
``HttpResponseRedirect`` rather than a normal ``HttpResponse``.
``HttpResponseRedirect`` takes a single argument: the URL to which the
- user will be redirected. You should leave off the "http://" and domain
- name if you can. That helps your app become portable across domains.
+ user will be redirected (see the following point for how we construct
+ the URL in this case).
As the Python comment above points out, you should always return an
``HttpResponseRedirect`` after successfully dealing with POST data. This
tip isn't specific to Django; it's just good Web development practice.
+ * We are using the ``reverse()`` function in the ``HttpResponseRedirect``
+ constructor in this example. This function helps avoid having to
+ hardcode a URL in the view function. It is given the name of the view
+ that we want to pass control to and the variable portion of the URL
+ pattern that points to that view. In this case, using the URLConf we set
+ up in Tutorial 3, this ``reverse()`` call will return a string like ::
+
+ '/polls/3/results/'
+
+ ... where the ``3`` is the value of ``p.id``. This redirected URL will
+ then call the ``'results'`` view to display the final page. Note that
+ you need to use the full name of the view here (including the prefix).
+
+ For more information about ``reverse()``, see the `URL dispatcher`_
+ documentation.
+
As mentioned in Tutorial 3, ``request`` is a ``HTTPRequest`` object. For more
on ``HTTPRequest`` objects, see the `request and response documentation`_.
@@ -120,7 +137,8 @@ Now, go to ``/polls/1/`` in your browser and vote in the poll. You should see a
results page that gets updated each time you vote. If you submit the form
without having chosen a choice, you should see the error message.
-.. _request and response documentation: http://www.djangoproject.com/documentation/request_response/
+.. _request and response documentation: ../request_response/
+.. _URL dispatcher: ../url_dispatch#reverse
Use generic views: Less code is better
======================================
@@ -206,6 +224,21 @@ for the polls app, we manually specify a template name for the results view:
``template_name='polls/results.html'``. Otherwise, both views would use the same
template. Note that we use ``dict()`` to return an altered dictionary in place.
+.. note:: ``all()`` is lazy
+
+ It might look a little frightening to see ``Poll.objects.all()`` being used
+ in a detail view which only needs one ``Poll`` object, but don't worry;
+ ``Poll.objects.all()`` is actually a special object called a ``QuerySet``,
+ which is "lazy" and doesn't hit your database until it absolutely has to. By
+ the time the database query happens, the ``object_detail`` generic view will
+ have narrowed its scope down to a single object, so the eventual query will
+ only select one row from the database.
+
+ If you'd like to know more about how that works, The Django database API
+ documentation `explains the lazy nature of QuerySet objects`_.
+
+.. _explains the lazy nature of QuerySet objects: ../db-api/#querysets-are-lazy
+
In previous parts of the tutorial, the templates have been provided with a context
that contains the ``poll`` and ``latest_poll_list`` context variables. However,
the generic views provide the variables ``object`` and ``object_list`` as context.
@@ -226,7 +259,7 @@ Run the server, and use your new polling app based on generic views.
For full details on generic views, see the `generic views documentation`_.
-.. _generic views documentation: http://www.djangoproject.com/documentation/generic_views/
+.. _generic views documentation: ../generic_views/
Coming soon
===========
@@ -241,4 +274,8 @@ installments:
* Advanced admin features: Permissions
* Advanced admin features: Custom JavaScript
-.. _Tutorial 3: http://www.djangoproject.com/documentation/tutorial3/
+In the meantime, you can read through the rest of the `Django documentation`_
+and start writing your own applications.
+
+.. _Tutorial 3: ../tutorial03/
+.. _Django documentation: http://www.djangoproject.com/documentation/
diff --git a/docs/url_dispatch.txt b/docs/url_dispatch.txt
index 00a7af027a..402b1200b5 100644
--- a/docs/url_dispatch.txt
+++ b/docs/url_dispatch.txt
@@ -45,8 +45,8 @@ algorithm the system follows to determine which Python code to execute:
`request object`_ as its first argument and any values captured in the
regex as remaining arguments.
-.. _settings file: http://www.djangoproject.com/documentation/settings/
-.. _request object: http://www.djangoproject.com/documentation/request_response/#httprequest-objects
+.. _settings file: ../settings/
+.. _request object: ../request_response/#httprequest-objects
Example
=======
@@ -185,10 +185,26 @@ The first argument to ``patterns()`` is a string ``prefix``. See
The remaining arguments should be tuples in this format::
- (regular expression, Python callback function [, optional dictionary])
+ (regular expression, Python callback function [, optional dictionary [, optional name]])
-...where ``optional dictionary`` is optional. (See
-_`Passing extra options to view functions` below.)
+...where ``optional dictionary`` and ``optional name`` are optional. (See
+`Passing extra options to view functions`_ below.)
+
+url
+---
+
+**New in Django development version**
+
+You can use the ``url()`` function, instead of a tuple, as an argument to
+``patterns()``. This is convenient if you want to specify a name without the
+optional extra arguments dictionary. For example::
+
+ urlpatterns = patterns('',
+ url(r'/index/$', index_view, name="main-view"),
+ ...
+ )
+
+See `Naming URL patterns`_ for why the ``name`` parameter is useful.
handler404
----------
@@ -286,7 +302,7 @@ With this in mind, the above example can be written more concisely as::
Note that you don't put a trailing dot (``"."``) in the prefix. Django puts
that in automatically.
-.. _Django overview: http://www.djangoproject.com/documentation/overview/
+.. _Django overview: ../overview/
Multiple view prefixes
----------------------
@@ -387,14 +403,19 @@ In this example, for a request to ``/blog/2005/``, Django will call the
This technique is used in `generic views`_ and in the `syndication framework`_
to pass metadata and options to views.
-.. _generic views: http://www.djangoproject.com/documentation/generic_views/
-.. _syndication framework: http://www.djangoproject.com/documentation/syndication/
+.. _generic views: ../generic_views/
+.. _syndication framework: ../syndication/
+
+.. admonition:: Dealing with conflicts
+
+ It's possible to have a URL pattern which captures named keyword arguments,
+ and also passes arguments with the same names in its dictionary of extra
+ arguments. When this happens, the arguments in the dictionary will be used
+ instead of the arguments captured in the URL.
Passing extra options to ``include()``
--------------------------------------
-**New in the Django development version.**
-
Similarly, you can pass extra options to ``include()``. When you pass extra
options to ``include()``, *each* line in the included URLconf will be passed
the extra options.
@@ -435,8 +456,6 @@ every view in the the included URLconf accepts the extra options you're passing.
Passing callable objects instead of strings
===========================================
-**New in the Django development version.**
-
Some developers find it more natural to pass the actual Python function object
rather than a string containing the path to its module. This alternative is
supported -- you can pass any callable object as the view.
@@ -476,3 +495,94 @@ The style you use is up to you.
Note that if you use this technique -- passing objects rather than strings --
the view prefix (as explained in "The view prefix" above) will have no effect.
+
+Naming URL patterns
+===================
+
+**New in Django development version**
+
+It's fairly common to use the same view function in multiple URL patterns in
+your URLconf. For example, these two URL patterns both point to the ``archive``
+view::
+
+ urlpatterns = patterns('',
+ (r'/archive/(\d{4})/$', archive),
+ (r'/archive-summary/(\d{4})/$', archive, {'summary': True}),
+ )
+
+This is completely valid, but it leads to problems when you try to do reverse
+URL matching (through the ``permalink()`` decorator or the ``{% url %}``
+template tag). Continuing this example, if you wanted to retrieve the URL for
+the ``archive`` view, Django's reverse URL matcher would get confused, because
+*two* URLpatterns point at that view.
+
+To solve this problem, Django supports **named URL patterns**. That is, you can
+give a name to a URL pattern in order to distinguish it from other patterns
+using the same view and parameters. Then, you can use this name in reverse URL
+matching.
+
+Here's the above example, rewritten to used named URL patterns::
+
+ urlpatterns = patterns('',
+ url(r'/archive/(\d{4})/$', archive, name="full-archive"),
+ url(r'/archive-summary/(\d{4})/$', archive, {'summary': True}, "arch-summary"),
+ )
+
+With these names in place (``full-archive`` and ``arch-summary``), you can
+target each pattern individually by using its name::
+
+ {% url arch-summary 1945 %}
+ {% url full-archive 2007 %}
+
+Even though both URL patterns refer to the ``archive`` view here, using the
+``name`` parameter to ``url()`` allows you to tell them apart in templates.
+
+The string used for the URL name can contain any characters you like. You are
+not restricted to valid Python names.
+
+.. note::
+
+ When you name your URL patterns, make sure you use names that are unlikely
+ to clash with any other application's choice of names. If you call your URL
+ pattern ``comment``, and another application does the same thing, there's
+ no guarantee which URL will be inserted into your template when you use
+ this name.
+
+ Putting a prefix on your URL names, perhaps derived from the application
+ name, will decrease the chances of collision. We recommend something like
+ ``myapp-comment`` instead of ``comment``.
+
+Utility methods
+===============
+
+reverse()
+---------
+
+If you need to use something similar to the ``{% url %}`` template tag in your
+code, Django provides the ``django.core.urlresolvers.reverse()``. The
+``reverse()`` function has the following signature::
+
+ reverse(viewname, urlconf=None, args=None, kwargs=None)
+
+``viewname`` is either the function name (either a function reference, or the
+string version of the name, if you used that form in ``urlpatterns``) or the
+`URL pattern name`_. Normally, you won't need to worry about the
+``urlconf`` parameter and will only pass in the positional and keyword
+arguments to use in the URL matching. For example::
+
+ from django.core.urlresolvers import reverse
+
+ def myview(request):
+ return HttpResponseRedirect(reverse('arch-summary', args=[1945]))
+
+.. _URL pattern name: `Naming URL patterns`_
+
+permalink()
+-----------
+
+The ``permalink()`` decorator is useful for writing short methods that return
+a full URL path. For example, a model's ``get_absolute_url()`` method. Refer
+to the `model API documentation`_ for more information about ``permalink()``.
+
+.. _model API documentation: ../model-api/#the-permalink-decorator
+
diff --git a/docs/webdesign.txt b/docs/webdesign.txt
new file mode 100644
index 0000000000..8e6eae89dd
--- /dev/null
+++ b/docs/webdesign.txt
@@ -0,0 +1,53 @@
+========================
+django.contrib.webdesign
+========================
+
+The ``django.contrib.webdesign`` package, part of the `"django.contrib" add-ons`_,
+provides various Django helpers that are particularly useful to Web *designers*
+(as opposed to developers).
+
+At present, the package contains only a single template tag. If you have ideas
+for Web-designer-friendly functionality in Django, please `suggest them`_.
+
+.. _"django.contrib" add-ons: ../add_ons/
+.. _suggest them: ../contributing/
+
+Template tags
+=============
+
+To use these template tags, add ``'django.contrib.webdesign'`` to your
+``INSTALLED_APPS`` setting. Once you've done that, use
+``{% load webdesign %}`` in a template to give your template access to the tags.
+
+
+lorem
+=====
+
+Displays random "lorem ipsum" Latin text. This is useful for providing sample
+data in templates.
+
+Usage::
+
+ {% lorem [count] [method] [random] %}
+
+The ``{% lorem %}`` tag can be used with zero, one, two or three arguments.
+The arguments are:
+
+ =========== =============================================================
+ Argument Description
+ =========== =============================================================
+ ``count`` A number (or variable) containing the number of paragraphs or
+ words to generate (default is 1).
+ ``method`` Either ``w`` for words, ``p`` for HTML paragraphs or ``b``
+ for plain-text paragraph blocks (default is ``b``).
+ ``random`` The word ``random``, which if given, does not use the common
+ paragraph ("Lorem ipsum dolor sit amet...") when generating
+ text.
+ =========== =============================================================
+
+Examples:
+
+ * ``{% lorem %}`` will output the common "lorem ipsum" paragraph.
+ * ``{% lorem 3 p %}`` will output the common "lorem ipsum" paragraph
+ and two random paragraphs each wrapped in HTML ``<p>`` tags.
+ * ``{% lorem 2 w random %}`` will output two random Latin words.