summaryrefslogtreecommitdiff
path: root/docs/ref
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2013-08-09 14:17:30 +0100
committerAndrew Godwin <andrew@aeracode.org>2013-08-09 14:17:30 +0100
commitde64c4d6e97c980fb4c0ace045fc4070b3f763d9 (patch)
tree045c8af6a88fa964cf7e284970a6e93d53941a79 /docs/ref
parentfddc5957c53bd654312c4a238a8cdcfe5f4ef4cc (diff)
parentb575d690bbc1c4cd7f575346132c09fca8c736a7 (diff)
Merge remote-tracking branch 'core/master' into schema-alteration
Conflicts: django/core/management/commands/flush.py django/core/management/commands/syncdb.py django/db/models/loading.py docs/internals/deprecation.txt docs/ref/django-admin.txt docs/releases/1.7.txt
Diffstat (limited to 'docs/ref')
-rw-r--r--docs/ref/class-based-views/base.txt2
-rw-r--r--docs/ref/class-based-views/mixins-date-based.txt2
-rw-r--r--docs/ref/class-based-views/mixins-multiple-object.txt8
-rw-r--r--docs/ref/class-based-views/mixins-single-object.txt8
-rw-r--r--docs/ref/contrib/admin/actions.txt2
-rw-r--r--docs/ref/contrib/admin/index.txt31
-rw-r--r--docs/ref/contrib/auth.txt14
-rw-r--r--docs/ref/contrib/comments/moderation.txt2
-rw-r--r--docs/ref/contrib/sitemaps.txt9
-rw-r--r--docs/ref/contrib/staticfiles.txt8
-rw-r--r--docs/ref/contrib/syndication.txt26
-rw-r--r--docs/ref/django-admin.txt26
-rw-r--r--docs/ref/exceptions.txt48
-rw-r--r--docs/ref/forms/api.txt15
-rw-r--r--docs/ref/forms/fields.txt41
-rw-r--r--docs/ref/forms/validation.txt16
-rw-r--r--docs/ref/forms/widgets.txt7
-rw-r--r--docs/ref/middleware.txt2
-rw-r--r--docs/ref/models/fields.txt22
-rw-r--r--docs/ref/models/instances.txt24
-rw-r--r--docs/ref/models/options.txt7
-rw-r--r--docs/ref/models/querysets.txt145
-rw-r--r--docs/ref/request-response.txt20
-rw-r--r--docs/ref/settings.txt4
-rw-r--r--docs/ref/templates/api.txt2
-rw-r--r--docs/ref/utils.txt62
26 files changed, 424 insertions, 129 deletions
diff --git a/docs/ref/class-based-views/base.txt b/docs/ref/class-based-views/base.txt
index 4ad017c342..24058311a4 100644
--- a/docs/ref/class-based-views/base.txt
+++ b/docs/ref/class-based-views/base.txt
@@ -222,6 +222,8 @@ RedirectView
.. attribute:: pattern_name
+ .. versionadded:: 1.6
+
The name of the URL pattern to redirect to. Reversing will be done
using the same args and kwargs as are passed in for this view.
diff --git a/docs/ref/class-based-views/mixins-date-based.txt b/docs/ref/class-based-views/mixins-date-based.txt
index 1a1a4d531b..1162b2a194 100644
--- a/docs/ref/class-based-views/mixins-date-based.txt
+++ b/docs/ref/class-based-views/mixins-date-based.txt
@@ -225,7 +225,7 @@ DateMixin
.. attribute:: date_field
The name of the ``DateField`` or ``DateTimeField`` in the
- ``QuerySet``'s model that the date-based archive should use to
+ ``QuerySet``’s model that the date-based archive should use to
determine the list of objects to display on the page.
When :doc:`time zone support </topics/i18n/timezones>` is enabled and
diff --git a/docs/ref/class-based-views/mixins-multiple-object.txt b/docs/ref/class-based-views/mixins-multiple-object.txt
index b28bd11a71..67ca5429fa 100644
--- a/docs/ref/class-based-views/mixins-multiple-object.txt
+++ b/docs/ref/class-based-views/mixins-multiple-object.txt
@@ -63,6 +63,14 @@ MultipleObjectMixin
A ``QuerySet`` that represents the objects. If provided, the value of
``queryset`` supersedes the value provided for :attr:`model`.
+ .. warning::
+
+ ``queryset`` is a class attribute with a *mutable* value so care
+ must be taken when using it directly. Before using it, either call
+ its :meth:`~django.db.models.query.QuerySet.all` method or
+ retrieve it with :meth:`get_queryset` which takes care of the
+ cloning behind the scenes.
+
.. attribute:: paginate_by
An integer specifying how many objects should be displayed per page. If
diff --git a/docs/ref/class-based-views/mixins-single-object.txt b/docs/ref/class-based-views/mixins-single-object.txt
index bbe930d79e..1fce24acc5 100644
--- a/docs/ref/class-based-views/mixins-single-object.txt
+++ b/docs/ref/class-based-views/mixins-single-object.txt
@@ -23,6 +23,14 @@ SingleObjectMixin
A ``QuerySet`` that represents the objects. If provided, the value of
``queryset`` supersedes the value provided for :attr:`model`.
+ .. warning::
+
+ ``queryset`` is a class attribute with a *mutable* value so care
+ must be taken when using it directly. Before using it, either call
+ its :meth:`~django.db.models.query.QuerySet.all` method or
+ retrieve it with :meth:`get_queryset` which takes care of the
+ cloning behind the scenes.
+
.. attribute:: slug_field
The name of the field on the model that contains the slug. By default,
diff --git a/docs/ref/contrib/admin/actions.txt b/docs/ref/contrib/admin/actions.txt
index 65d096921f..58d8244525 100644
--- a/docs/ref/contrib/admin/actions.txt
+++ b/docs/ref/contrib/admin/actions.txt
@@ -271,7 +271,7 @@ Making actions available site-wide
This makes the `export_selected_objects` action globally available as an
action named `"export_selected_objects"`. You can explicitly give the action
- a name -- good if you later want to programatically :ref:`remove the action
+ a name -- good if you later want to programmatically :ref:`remove the action
<disabling-admin-actions>` -- by passing a second argument to
:meth:`AdminSite.add_action()`::
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
index e5e9428805..8feb574efd 100644
--- a/docs/ref/contrib/admin/index.txt
+++ b/docs/ref/contrib/admin/index.txt
@@ -1218,6 +1218,14 @@ templates used by the :class:`ModelAdmin` views:
changelist that will be linked to the change view, as described in the
:attr:`ModelAdmin.list_display_links` section.
+.. method:: ModelAdmin.get_fields(self, request, obj=None)
+
+ .. versionadded:: 1.7
+
+ The ``get_fields`` method is given the ``HttpRequest`` and the ``obj``
+ being edited (or ``None`` on an add form) and is expected to return a list
+ of fields, as described above in the :attr:`ModelAdmin.fields` section.
+
.. method:: ModelAdmin.get_fieldsets(self, request, obj=None)
The ``get_fieldsets`` method is given the ``HttpRequest`` and the ``obj``
@@ -1233,6 +1241,14 @@ templates used by the :class:`ModelAdmin` views:
to return the same kind of sequence type as for the
:attr:`~ModelAdmin.list_filter` attribute.
+.. method:: ModelAdmin.get_search_fields(self, request)
+
+ .. versionadded:: 1.7
+
+ The ``get_search_fields`` method is given the ``HttpRequest`` and is expected
+ to return the same kind of sequence type as for the
+ :attr:`~ModelAdmin.search_fields` attribute.
+
.. method:: ModelAdmin.get_inline_instances(self, request, obj=None)
.. versionadded:: 1.5
@@ -1389,6 +1405,15 @@ templates used by the :class:`ModelAdmin` views:
kwargs['choices'] += (('ready', 'Ready for deployment'),)
return super(MyModelAdmin, self).formfield_for_choice_field(db_field, request, **kwargs)
+ .. admonition:: Note
+
+ Any ``choices`` attribute set on the formfield will limited to the form
+ field only. If the corresponding field on the model has choices set,
+ the choices provided to the form must be a valid subset of those
+ choices, otherwise the form submission will fail with
+ a :exc:`~django.core.exceptions.ValidationError` when the model itself
+ is validated before saving.
+
.. method:: ModelAdmin.get_changelist(self, request, **kwargs)
Returns the ``Changelist`` class to be used for listing. By default,
@@ -1590,7 +1615,7 @@ in your own admin JavaScript without including a second copy, you can use the
The embedded jQuery has been upgraded from 1.4.2 to 1.9.1.
The :class:`ModelAdmin` class requires jQuery by default, so there is no need
-to add jQuery to your ``ModelAdmin``'s list of media resources unless you have
+to add jQuery to your ``ModelAdmin``’s list of media resources unless you have
a specifc need. For example, if you require the jQuery library to be in the
global namespace (for example when using third-party jQuery plugins) or if you
need a newer version of jQuery, you will have to include your own copy.
@@ -2162,6 +2187,10 @@ Templates can override or extend base admin templates as described in
Path to a custom template that will be used by the admin site main index
view.
+.. attribute:: AdminSite.app_index_template
+
+ Path to a custom template that will be used by the admin site app index view.
+
.. attribute:: AdminSite.login_template
Path to a custom template that will be used by the admin site login view.
diff --git a/docs/ref/contrib/auth.txt b/docs/ref/contrib/auth.txt
index dfda8add4b..4fe87e9872 100644
--- a/docs/ref/contrib/auth.txt
+++ b/docs/ref/contrib/auth.txt
@@ -114,11 +114,13 @@ Methods
Always returns ``True`` (as opposed to
``AnonymousUser.is_authenticated()`` which always returns ``False``).
This is a way to tell if the user has been authenticated. This does not
- imply any permissions, and doesn't check if the user is active - it
- only indicates that ``request.user`` has been populated by the
- :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` with
- a :class:`~django.contrib.auth.models.User` object representing the
- currently logged-in user.
+ imply any permissions, and doesn't check if the user is active or has
+ a valid session. Even though normally you will call this method on
+ ``request.user`` to find out whether it has been populated by the
+ :class:`~django.contrib.auth.middleware.AuthenticationMiddleware`
+ (representing the currently logged-in user), you should know this method
+ returns ``True`` for any :class:`~django.contrib.auth.models.User`
+ instance.
.. method:: get_full_name()
@@ -243,7 +245,7 @@ Manager methods
be called.
The ``extra_fields`` keyword arguments are passed through to the
- :class:`~django.contrib.auth.models.User`'s ``__init__`` method to
+ :class:`~django.contrib.auth.models.User`’s ``__init__`` method to
allow setting arbitrary fields on a :ref:`custom User model
<auth-custom-user>`.
diff --git a/docs/ref/contrib/comments/moderation.txt b/docs/ref/contrib/comments/moderation.txt
index 796e257200..5f0badfadb 100644
--- a/docs/ref/contrib/comments/moderation.txt
+++ b/docs/ref/contrib/comments/moderation.txt
@@ -54,7 +54,7 @@ following model, which would represent entries in a Weblog::
Now, suppose that we want the following steps to be applied whenever a
new comment is posted on an ``Entry``:
-1. If the ``Entry``'s ``enable_comments`` field is ``False``, the
+1. If the ``Entry``’s ``enable_comments`` field is ``False``, the
comment will simply be disallowed (i.e., immediately deleted).
2. If the ``enable_comments`` field is ``True``, the comment will be
diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt
index 4467ed3a6e..7b53fc8c12 100644
--- a/docs/ref/contrib/sitemaps.txt
+++ b/docs/ref/contrib/sitemaps.txt
@@ -178,6 +178,15 @@ Sitemap class reference
representing the last-modified date/time for *every* object returned by
:attr:`~Sitemap.items()`.
+ .. versionadded:: 1.7
+
+ If all items in a sitemap have a :attr:`~Sitemap.lastmod`, the sitemap
+ generated by :func:`views.sitemap` will have a ``Last-Modified``
+ header equal to the latest ``lastmod``. You can activate the
+ :class:`~django.middleware.http.ConditionalGetMiddleware` to make
+ Django respond appropriately to requests with an ``If-Modified-Since``
+ header which will prevent sending the sitemap if it hasn't changed.
+
.. attribute:: Sitemap.changefreq
**Optional.** Either a method or attribute.
diff --git a/docs/ref/contrib/staticfiles.txt b/docs/ref/contrib/staticfiles.txt
index 806d135deb..f96c2e8a1b 100644
--- a/docs/ref/contrib/staticfiles.txt
+++ b/docs/ref/contrib/staticfiles.txt
@@ -226,7 +226,7 @@ CachedStaticFilesStorage
would be replaced by calling the
:meth:`~django.core.files.storage.Storage.url`
- method of the ``CachedStaticFilesStorage`` storage backend, ultimatively
+ method of the ``CachedStaticFilesStorage`` storage backend, ultimately
saving a ``'css/styles.55e7cbb9ba48.css'`` file with the following
content:
@@ -350,6 +350,12 @@ This view function serves static files in development.
**insecure**. This is only intended for local development, and should
**never be used in production**.
+.. versionchanged:: 1.7
+
+ This view will now raise an :exc:`~django.http.Http404` exception instead
+ of :exc:`~django.core.exceptions.ImproperlyConfigured` when
+ :setting:`DEBUG` is ``False``.
+
.. note::
To guess the served files' content types, this view relies on the
diff --git a/docs/ref/contrib/syndication.txt b/docs/ref/contrib/syndication.txt
index 9a0fb5830e..996950ef56 100644
--- a/docs/ref/contrib/syndication.txt
+++ b/docs/ref/contrib/syndication.txt
@@ -49,17 +49,17 @@ are views which can be used in your :doc:`URLconf </topics/http/urls>`.
A simple example
----------------
-This simple example, taken from `chicagocrime.org`_, describes a feed of the
-latest five news items::
+This simple example, taken from a hypothetical police beat news site describes
+a feed of the latest five news items::
from django.contrib.syndication.views import Feed
from django.core.urlresolvers import reverse
- from chicagocrime.models import NewsItem
+ from policebeat.models import NewsItem
class LatestEntriesFeed(Feed):
- title = "Chicagocrime.org site news"
+ title = "Police beat site news"
link = "/sitenews/"
- description = "Updates on changes and additions to chicagocrime.org."
+ description = "Updates on changes and additions to police beat central."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
@@ -199,22 +199,20 @@ into those elements.
are responsible for doing all necessary URL quoting and conversion to
ASCII inside the method itself.
-.. _chicagocrime.org: http://www.chicagocrime.org/
-
A complex example
-----------------
The framework also supports more complex feeds, via arguments.
-For example, `chicagocrime.org`_ offers an RSS feed of recent crimes for every
-police beat in Chicago. It'd be silly to create a separate
+For example, a website could offer an RSS feed of recent crimes for every
+police beat in a city. It'd be silly to create a separate
:class:`~django.contrib.syndication.views.Feed` class for each police beat; that
would violate the :ref:`DRY principle <dry>` and would couple data to
programming logic. Instead, the syndication framework lets you access the
arguments passed from your :doc:`URLconf </topics/http/urls>` so feeds can output
items based on information in the feed's URL.
-On chicagocrime.org, the police-beat feeds are accessible via URLs like this:
+The police beat feeds could be accessible via URLs like this:
* :file:`/beats/613/rss/` -- Returns recent crimes for beat 613.
* :file:`/beats/1424/rss/` -- Returns recent crimes for beat 1424.
@@ -238,7 +236,7 @@ Here's the code for these beat-specific feeds::
return get_object_or_404(Beat, pk=beat_id)
def title(self, obj):
- return "Chicagocrime.org: Crimes for beat %s" % obj.beat
+ return "Police beat central: Crimes for beat %s" % obj.beat
def link(self, obj):
return obj.get_absolute_url()
@@ -339,13 +337,13 @@ URLconf to add the extra versions.
Here's a full example::
from django.contrib.syndication.views import Feed
- from chicagocrime.models import NewsItem
+ from policebeat.models import NewsItem
from django.utils.feedgenerator import Atom1Feed
class RssSiteNewsFeed(Feed):
- title = "Chicagocrime.org site news"
+ title = "Police beat site news"
link = "/sitenews/"
- description = "Updates on changes and additions to chicagocrime.org."
+ description = "Updates on changes and additions to police beat central."
def items(self):
return NewsItem.objects.order_by('-pub_date')[:5]
diff --git a/docs/ref/django-admin.txt b/docs/ref/django-admin.txt
index 05fc8a1191..ab83e2cf33 100644
--- a/docs/ref/django-admin.txt
+++ b/docs/ref/django-admin.txt
@@ -233,7 +233,7 @@ probably be using this flag.
.. django-admin-option:: --pks
By default, ``dumpdata`` will output all the records of the model, but
-you can use the ``--pks`` option to specify a comma seperated list of
+you can use the ``--pks`` option to specify a comma separated list of
primary keys on which to filter. This is only available when dumping
one model.
@@ -251,8 +251,8 @@ prompts.
The :djadminopt:`--database` option may be used to specify the database
to flush.
---no-initial-data
-~~~~~~~~~~~~~~~~~
+``--no-initial-data``
+~~~~~~~~~~~~~~~~~~~~~
.. versionadded:: 1.5
@@ -558,7 +558,7 @@ several lines in language files.
.. django-admin-option:: --no-location
-Use the ``--no-location`` option to not write '``#: filename:line``'
+Use the ``--no-location`` option to not write '``#: filename:line``’
comment lines in language files. Note that using this option makes it harder
for technically skilled translators to understand each message's context.
@@ -617,6 +617,9 @@ runfcgi [options]
.. django-admin:: runfcgi
+.. deprecated:: 1.7
+ FastCGI support is deprecated and will be removed in Django 1.9.
+
Starts a set of FastCGI processes suitable for use with any Web server that
supports the FastCGI protocol. See the :doc:`FastCGI deployment documentation
</howto/deployment/fastcgi>` for details. Requires the Python FastCGI module from
@@ -780,7 +783,7 @@ You can provide an IPv6 address surrounded by brackets
A hostname containing ASCII-only characters can also be used.
If the :doc:`staticfiles</ref/contrib/staticfiles>` contrib app is enabled
-(default in new projects) the :djadmin:`runserver` command will be overriden
+(default in new projects) the :djadmin:`runserver` command will be overridden
with its own :ref:`runserver<staticfiles-runserver>` command.
.. django-admin-option:: --noreload
@@ -1432,6 +1435,19 @@ that ``django-admin.py`` should print to the console.
* ``2`` means verbose output.
* ``3`` means *very* verbose output.
+.. django-admin-option:: --no-color
+
+.. versionadded:: 1.7
+
+Example usage::
+
+ django-admin.py sqlall --no-color
+
+By default, ``django-admin.py`` will format the output to be colorized. For
+example, errors will be printed to the console in red and SQL statements will
+be syntax highlighted. To prevent this and have a plain text output, pass the
+``--no-color`` option when running your command.
+
Common options
==============
diff --git a/docs/ref/exceptions.txt b/docs/ref/exceptions.txt
index b15bbea8fa..bee8559ab0 100644
--- a/docs/ref/exceptions.txt
+++ b/docs/ref/exceptions.txt
@@ -6,24 +6,29 @@ Django Exceptions
Django raises some Django specific exceptions as well as many standard
Python exceptions.
-Django-specific Exceptions
-==========================
+Django Core Exceptions
+======================
.. module:: django.core.exceptions
- :synopsis: Django specific exceptions
+ :synopsis: Django core exceptions
+
+Django core exception classes are defined in :mod:`django.core.exceptions`.
ObjectDoesNotExist and DoesNotExist
-----------------------------------
.. exception:: DoesNotExist
-.. exception:: ObjectDoesNotExist
- The :exc:`DoesNotExist` exception is raised when an object is not found
- for the given parameters of a query.
+ The ``DoesNotExist`` exception is raised when an object is not found for
+ the given parameters of a query. Django provides a ``DoesNotExist``
+ exception as an attribute of each model class to identify the class of
+ object that could not be found and to allow you to catch a particular model
+ class with ``try/except``.
+
+.. exception:: ObjectDoesNotExist
- :exc:`ObjectDoesNotExist` is defined in :mod:`django.core.exceptions`.
- :exc:`DoesNotExist` is a subclass of the base :exc:`ObjectDoesNotExist`
- exception that is provided on every model class as a way of
- identifying the specific type of object that could not be found.
+ The base class for ``DoesNotExist`` exceptions; a ``try/except`` for
+ ``ObjectDoesNotExist`` will catch ``DoesNotExist`` exceptions for all
+ models.
See :meth:`~django.db.models.query.QuerySet.get()` for further information
on :exc:`ObjectDoesNotExist` and :exc:`DoesNotExist`.
@@ -121,6 +126,11 @@ ValidationError
.. currentmodule:: django.core.urlresolvers
+URL Resolver exceptions
+=======================
+
+URL Resolver exceptions are defined in :mod:`django.core.urlresolvers`.
+
NoReverseMatch
--------------
.. exception:: NoReverseMatch
@@ -134,9 +144,10 @@ NoReverseMatch
Database Exceptions
===================
+Database exceptions are provided in :mod:`django.db`.
+
Django wraps the standard database exceptions so that your Django code has a
-guaranteed common implementation of these classes. These database exceptions
-are provided in :mod:`django.db`.
+guaranteed common implementation of these classes.
.. exception:: Error
.. exception:: InterfaceError
@@ -160,34 +171,37 @@ to Python 3.)
.. versionchanged:: 1.6
- Previous version of Django only wrapped ``DatabaseError`` and
+ Previous versions of Django only wrapped ``DatabaseError`` and
``IntegrityError``, and did not provide ``__cause__``.
.. exception:: models.ProtectedError
Raised to prevent deletion of referenced objects when using
-:attr:`django.db.models.PROTECT`. Subclass of :exc:`IntegrityError`.
+:attr:`django.db.models.PROTECT`. :exc:`models.ProtectedError` is a subclass
+of :exc:`IntegrityError`.
.. currentmodule:: django.http
Http Exceptions
===============
+Http exceptions are provided in :mod:`django.http`.
+
.. exception:: UnreadablePostError
The :exc:`UnreadablePostError` is raised when a user cancels an upload.
- It is available from :mod:`django.http`.
.. currentmodule:: django.db.transaction
Transaction Exceptions
======================
+Transaction exceptions are defined in :mod:`django.db.transaction`.
+
.. exception:: TransactionManagementError
The :exc:`TransactionManagementError` is raised for any and all problems
- related to database transactions. It is available from
- :mod:`django.db.transaction`.
+ related to database transactions.
Python Exceptions
=================
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index 7c1601d3ea..780cb5d4f7 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -527,6 +527,11 @@ Note that the label suffix is added only if the last character of the
label isn't a punctuation character (in English, those are ``.``, ``!``, ``?``
or ``:``).
+.. versionadded:: 1.6
+
+You can also customize the ``label_suffix`` on a per-field basis using the
+``label_suffix`` parameter to :meth:`~django.forms.BoundField.label_tag`.
+
Notes on field ordering
~~~~~~~~~~~~~~~~~~~~~~~
@@ -653,7 +658,7 @@ when printed::
>>> str(f['subject'].errors)
''
-.. method:: BoundField.label_tag(contents=None, attrs=None)
+.. method:: BoundField.label_tag(contents=None, attrs=None, label_suffix=None)
To separately render the label tag of a form field, you can call its
``label_tag`` method::
@@ -671,6 +676,14 @@ additional attributes for the ``<label>`` tag.
The label now includes the form's :attr:`~django.forms.Form.label_suffix`
(a colon, by default).
+.. versionadded:: 1.6
+
+ The optional ``label_suffix`` parameter allows you to override the form's
+ :attr:`~django.forms.Form.label_suffix`. For example, you can use an empty
+ string to hide the label on selected fields. If you need to do this in a
+ template, you could write a custom filter to allow passing parameters to
+ ``label_tag``.
+
.. method:: BoundField.css_classes()
When you use Django's rendering shortcuts, CSS classes are used to
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
index ef4ed729bd..e7c6612a72 100644
--- a/docs/ref/forms/fields.txt
+++ b/docs/ref/forms/fields.txt
@@ -877,7 +877,7 @@ Slightly complex built-in ``Field`` classes
* Normalizes to: the type returned by the ``compress`` method of the subclass.
* Validates that the given value against each of the fields specified
as an argument to the ``MultiValueField``.
- * Error message keys: ``required``, ``invalid``
+ * Error message keys: ``required``, ``invalid``, ``incomplete``
Aggregates the logic of multiple fields that together produce a single
value.
@@ -898,6 +898,45 @@ Slightly complex built-in ``Field`` classes
Once all fields are cleaned, the list of clean values is combined into
a single value by :meth:`~MultiValueField.compress`.
+ Also takes one extra optional argument:
+
+ .. attribute:: require_all_fields
+
+ .. versionadded:: 1.7
+
+ Defaults to ``True``, in which case a ``required`` validation error
+ will be raised if no value is supplied for any field.
+
+ When set to ``False``, the :attr:`Field.required` attribute can be set
+ to ``False`` for individual fields to make them optional. If no value
+ is supplied for a required field, an ``incomplete`` validation error
+ will be raised.
+
+ A default ``incomplete`` error message can be defined on the
+ :class:`MultiValueField` subclass, or different messages can be defined
+ on each individual field. For example::
+
+ from django.core.validators import RegexValidator
+
+ class PhoneField(MultiValueField):
+ def __init__(self, *args, **kwargs):
+ # Define one message for all fields.
+ error_messages = {
+ 'incomplete': 'Enter a country code and phone number.',
+ }
+ # Or define a different message for each field.
+ fields = (
+ CharField(error_messages={'incomplete': 'Enter a country code.'},
+ validators=[RegexValidator(r'^\d+$', 'Enter a valid country code.')]),
+ CharField(error_messages={'incomplete': 'Enter a phone number.'},
+ validators=[RegexValidator(r'^\d+$', 'Enter a valid phone number.')]),
+ CharField(validators=[RegexValidator(r'^\d+$', 'Enter a valid extension.')],
+ required=False),
+ )
+ super(PhoneField, self).__init__(
+ self, error_messages=error_messages, fields=fields,
+ require_all_fields=False, *args, **kwargs)
+
.. attribute:: MultiValueField.widget
Must be a subclass of :class:`django.forms.MultiWidget`.
diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt
index 8ab1c26831..255b665c42 100644
--- a/docs/ref/forms/validation.txt
+++ b/docs/ref/forms/validation.txt
@@ -75,10 +75,8 @@ overridden:
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``).
+ like. This method can return a completely different dictionary if it wishes,
+ which will be used as the ``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
@@ -171,7 +169,7 @@ following guidelines:
Putting it all together::
- raise ValidationErrror(
+ raise ValidationError(
_('Invalid value: %(value)s'),
code='invalid',
params={'value': '42'},
@@ -365,6 +363,8 @@ write a cleaning method that operates on the ``recipients`` field, like so::
Cleaning and validating fields that depend on each other
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.. method:: django.forms.Form.clean
+
Suppose we add another requirement to our contact form: if the ``cc_myself``
field is ``True``, the ``subject`` must contain the word ``"help"``. We are
performing validation on more than one field at a time, so the form's
@@ -403,9 +403,6 @@ example::
raise forms.ValidationError("Did not send for 'help' in "
"the subject despite CC'ing yourself.")
- # Always return the full collection of cleaned data.
- return cleaned_data
-
In this code, if the validation error is raised, the form will display an
error message at the top of the form (normally) describing the problem.
@@ -443,9 +440,6 @@ sample) looks like this::
del cleaned_data["cc_myself"]
del cleaned_data["subject"]
- # Always return the full collection of cleaned data.
- return cleaned_data
-
As you can see, this approach requires a bit more effort, not withstanding the
extra design effort to create a sensible form display. The details are worth
noting, however. Firstly, earlier we mentioned that you might need to check if
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index 5b66776cfc..080d1fea86 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -52,8 +52,7 @@ widget on the field. In the following example, the
:attr:`~django.forms.extras.widgets.SelectDateWidget.years` attribute is set
for a :class:`~django.forms.extras.widgets.SelectDateWidget`::
- from django.forms.fields import DateField, ChoiceField, MultipleChoiceField
- from django.forms.widgets import RadioSelect, CheckboxSelectMultiple
+ from django import forms
from django.forms.extras.widgets import SelectDateWidget
BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
@@ -62,9 +61,9 @@ for a :class:`~django.forms.extras.widgets.SelectDateWidget`::
('black', 'Black'))
class SimpleForm(forms.Form):
- birth_year = DateField(widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES))
+ birth_year = forms.DateField(widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES))
favorite_colors = forms.MultipleChoiceField(required=False,
- widget=CheckboxSelectMultiple, choices=FAVORITE_COLORS_CHOICES)
+ widget=forms.CheckboxSelectMultiple, choices=FAVORITE_COLORS_CHOICES)
See the :ref:`built-in widgets` for more information about which widgets
are available and which arguments they accept.
diff --git a/docs/ref/middleware.txt b/docs/ref/middleware.txt
index 4898bab636..d011f054ac 100644
--- a/docs/ref/middleware.txt
+++ b/docs/ref/middleware.txt
@@ -37,7 +37,7 @@ defines. See the :doc:`cache documentation </topics/cache>`.
Adds a few conveniences for perfectionists:
* Forbids access to user agents in the :setting:`DISALLOWED_USER_AGENTS`
- setting, which should be a list of strings.
+ setting, which should be a list of compiled regular expression objects.
* Performs URL rewriting based on the :setting:`APPEND_SLASH` and
:setting:`PREPEND_WWW` settings.
diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt
index 869996643f..01215884c4 100644
--- a/docs/ref/models/fields.txt
+++ b/docs/ref/models/fields.txt
@@ -152,11 +152,20 @@ method to retrieve the human-readable name for the field's current value. See
:meth:`~django.db.models.Model.get_FOO_display` in the database API
documentation.
-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 :attr:`~Field.choices` to be dynamic, you're probably better off using a
-proper database table with a :class:`ForeignKey`. :attr:`~Field.choices` is
-meant for static data that doesn't change much, if ever.
+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
+:attr:`~Field.choices` to be dynamic, you're probably better off using a proper
+database table with a :class:`ForeignKey`. :attr:`~Field.choices` is meant for
+static data that doesn't change much, if ever.
+
+.. versionadded:: 1.7
+
+Unless :attr:`blank=False<Field.blank>` is set on the field along with a
+:attr:`~Field.default` then a label containing ``"---------"`` will be rendered
+with the select box. To override this behavior, add a tuple to ``choices``
+containing ``None``; e.g. ``(None, 'Your String For Display')``.
+Alternatively, you can use an empty string instead of ``None`` where this makes
+sense - such as on a :class:`~django.db.models.CharField`.
``db_column``
-------------
@@ -874,6 +883,9 @@ are converted to lowercase.
``192.0.2.1``. Default is disabled. Can only be used
when ``protocol`` is set to ``'both'``.
+If you allow for blank values, you have to allow for null values since blank
+values are stored as null.
+
``NullBooleanField``
--------------------
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
index f06866d9a1..cb8570afdc 100644
--- a/docs/ref/models/instances.txt
+++ b/docs/ref/models/instances.txt
@@ -118,7 +118,7 @@ validation for your own manually created models. For example::
article.full_clean()
except ValidationError as e:
# Do something based on the errors contained in e.message_dict.
- # Display them to a user, or handle them programatically.
+ # Display them to a user, or handle them programmatically.
pass
The first step ``full_clean()`` performs is to clean each individual field.
@@ -140,15 +140,19 @@ attributes on your model if desired. For instance, you could use it to
automatically provide a value for a field, or to do validation that requires
access to more than a single field::
- def clean(self):
- import datetime
- from django.core.exceptions import ValidationError
- # Don't allow draft entries to have a pub_date.
- if self.status == 'draft' and self.pub_date is not None:
- raise ValidationError('Draft entries may not have a publication date.')
- # Set the pub_date for published items if it hasn't been set already.
- if self.status == 'published' and self.pub_date is None:
- self.pub_date = datetime.date.today()
+ import datetime
+ from django.core.exceptions import ValidationError
+ from django.db import models
+
+ class Article(models.Model):
+ ...
+ def clean(self):
+ # Don't allow draft entries to have a pub_date.
+ if self.status == 'draft' and self.pub_date is not None:
+ raise ValidationError('Draft entries may not have a publication date.')
+ # Set the pub_date for published items if it hasn't been set already.
+ if self.status == 'published' and self.pub_date is None:
+ self.pub_date = datetime.date.today()
Any :exc:`~django.core.exceptions.ValidationError` exceptions raised by
``Model.clean()`` will be stored in a special key error dictionary key,
diff --git a/docs/ref/models/options.txt b/docs/ref/models/options.txt
index 6eeed51b6f..6415a9d2da 100644
--- a/docs/ref/models/options.txt
+++ b/docs/ref/models/options.txt
@@ -90,7 +90,7 @@ Django quotes column and table names behind the scenes.
The name of an orderable field in the model, typically a :class:`DateField`,
:class:`DateTimeField`, or :class:`IntegerField`. This specifies the default
- field to use in your model :class:`Manager`'s
+ field to use in your model :class:`Manager`’s
:meth:`~django.db.models.query.QuerySet.latest` and
:meth:`~django.db.models.query.QuerySet.earliest` methods.
@@ -227,9 +227,8 @@ Django quotes column and table names behind the scenes.
.. attribute:: Options.permissions
Extra permissions to enter into the permissions table when creating this object.
- Add, delete and change permissions are automatically created for each object
- that has ``admin`` set. This example specifies an extra permission,
- ``can_deliver_pizzas``::
+ Add, delete and change permissions are automatically created for each
+ model. This example specifies an extra permission, ``can_deliver_pizzas``::
permissions = (("can_deliver_pizzas", "Can deliver pizzas"),)
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 3963785733..0f08022179 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -110,7 +110,7 @@ described here.
.. admonition:: You can't share pickles between versions
- Pickles of QuerySets are only valid for the version of Django that
+ Pickles of ``QuerySets`` are only valid for the version of Django that
was used to generate them. If you generate a pickle using Django
version N, there is no guarantee that pickle will be readable with
Django version N+1. Pickles should not be used as part of a long-term
@@ -121,9 +121,7 @@ described here.
QuerySet API
============
-Though you usually won't create one manually — you'll go through a
-:class:`~django.db.models.Manager` — here's the formal declaration of a
-``QuerySet``:
+Here's the formal declaration of a ``QuerySet``:
.. class:: QuerySet([model=None, query=None, using=None])
@@ -300,14 +298,30 @@ Be cautious when ordering by fields in related models if you are also using
:meth:`distinct()`. See the note in :meth:`distinct` for an explanation of how
related model ordering can change the expected results.
-It is permissible to specify a multi-valued field to order the results by (for
-example, a :class:`~django.db.models.ManyToManyField` field). Normally
-this won't be a sensible thing to do and it's really an advanced usage
-feature. However, if you know that your queryset's filtering or available data
-implies that there will only be one ordering piece of data for each of the main
-items you are selecting, the ordering may well be exactly what you want to do.
-Use ordering on multi-valued fields with care and make sure the results are
-what you expect.
+.. note::
+ It is permissible to specify a multi-valued field to order the results by
+ (for example, a :class:`~django.db.models.ManyToManyField` field, or the
+ reverse relation of a :class:`~django.db.models.ForeignKey` field).
+
+ Consider this case::
+
+ class Event(Model):
+ parent = models.ForeignKey('self', related_name='children')
+ date = models.DateField()
+
+ Event.objects.order_by('children__date')
+
+ Here, there could potentially be multiple ordering data for each ``Event``;
+ each ``Event`` with multiple ``children`` will be returned multiple times
+ into the new ``QuerySet`` that ``order_by()`` creates. In other words,
+ using ``order_by()`` on the ``QuerySet`` could return more items than you
+ were working on to begin with - which is probably neither expected nor
+ useful.
+
+ Thus, take care when using multi-valued field to order the results. **If**
+ you can be sure that there will only be one ordering piece of data for each
+ of the items you're ordering, this approach should not present problems. If
+ not, make sure the results are what you expect.
There's no way to specify whether ordering should be case sensitive. With
respect to case-sensitivity, Django will order results however your database
@@ -388,7 +402,7 @@ field names, the database will only compare the specified field names.
.. note::
When you specify field names, you *must* provide an ``order_by()`` in the
- QuerySet, and the fields in ``order_by()`` must start with the fields in
+ ``QuerySet``, and the fields in ``order_by()`` must start with the fields in
``distinct()``, in the same order.
For example, ``SELECT DISTINCT ON (a)`` gives you the first row for each
@@ -789,8 +803,8 @@ stop the deluge of database queries that is caused by accessing related objects,
but the strategy is quite different.
``select_related`` works by creating a SQL join and including the fields of the
-related object in the SELECT statement. For this reason, ``select_related`` gets
-the related objects in the same database query. However, to avoid the much
+related object in the ``SELECT`` statement. For this reason, ``select_related``
+gets the related objects in the same database query. However, to avoid the much
larger result set that would result from joining across a 'many' relationship,
``select_related`` is limited to single-valued relationships - foreign key and
one-to-one.
@@ -819,39 +833,54 @@ For example, suppose you have these models::
return u"%s (%s)" % (self.name, u", ".join([topping.name
for topping in self.toppings.all()]))
-and run this code::
+and run::
>>> Pizza.objects.all()
[u"Hawaiian (ham, pineapple)", u"Seafood (prawns, smoked salmon)"...
-The problem with this code is that it will run a query on the Toppings table for
-**every** item in the Pizza ``QuerySet``. Using ``prefetch_related``, this can
-be reduced to two:
+The problem with this is that every time ``Pizza.__unicode__()`` asks for
+``self.toppings.all()`` it has to query the database, so
+``Pizza.objects.all()`` will run a query on the Toppings table for **every**
+item in the Pizza ``QuerySet``.
+
+We can reduce to just two queries using ``prefetch_related``:
>>> Pizza.objects.all().prefetch_related('toppings')
-All the relevant toppings will be fetched in a single query, and used to make
-``QuerySets`` that have a pre-filled cache of the relevant results. These
-``QuerySets`` are then used in the ``self.toppings.all()`` calls.
+This implies a ``self.toppings.all()`` for each ``Pizza``; now each time
+``self.toppings.all()`` is called, instead of having to go to the database for
+the items, it will find them in a prefetched ``QuerySet`` cache that was
+populated in a single query.
-The additional queries are executed after the QuerySet has begun to be evaluated
-and the primary query has been executed. Note that the result cache of the
-primary QuerySet and all specified related objects will then be fully loaded
-into memory, which is often avoided in other cases - even after a query has been
-executed in the database, QuerySet normally tries to make uses of chunking
-between the database to avoid loading all objects into memory before you need
-them.
+That is, all the relevant toppings will have been fetched in a single query,
+and used to make ``QuerySets`` that have a pre-filled cache of the relevant
+results; these ``QuerySets`` are then used in the ``self.toppings.all()`` calls.
-Also remember that, as always with QuerySets, any subsequent chained methods
-which imply a different database query will ignore previously cached results,
-and retrieve data using a fresh database query. So, if you write the following:
+The additional queries in ``prefetch_related()`` are executed after the
+``QuerySet`` has begun to be evaluated and the primary query has been executed.
- >>> pizzas = Pizza.objects.prefetch_related('toppings')
- >>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]
+Note that the result cache of the primary ``QuerySet`` and all specified related
+objects will then be fully loaded into memory. This changes the typical
+behavior of ``QuerySets``, which normally try to avoid loading all objects into
+memory before they are needed, even after a query has been executed in the
+database.
-...then the fact that ``pizza.toppings.all()`` has been prefetched will not help
-you - in fact it hurts performance, since you have done a database query that
-you haven't used. So use this feature with caution!
+.. note::
+
+ Remember that, as always with ``QuerySets``, any subsequent chained methods
+ which imply a different database query will ignore previously cached
+ results, and retrieve data using a fresh database query. So, if you write
+ the following:
+
+ >>> pizzas = Pizza.objects.prefetch_related('toppings')
+ >>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]
+
+ ...then the fact that ``pizza.toppings.all()`` has been prefetched will not
+ help you. The ``prefetch_related('toppings')`` implied
+ ``pizza.toppings.all()``, but ``pizza.toppings.filter()`` is a new and
+ different query. The prefetched cache can't help here; in fact it hurts
+ performance, since you have done a database query that you haven't used. So
+ use this feature with caution!
You can also use the normal join syntax to do related fields of related
fields. Suppose we have an additional model to the example above::
@@ -904,7 +933,7 @@ additional queries on the ``ContentType`` table if the relevant rows have not
already been fetched.
``prefetch_related`` in most cases will be implemented using a SQL query that
-uses the 'IN' operator. This means that for a large QuerySet a large 'IN' clause
+uses the 'IN' operator. This means that for a large ``QuerySet`` a large 'IN' clause
could be generated, which, depending on the database, might have performance
problems of its own when it comes to parsing or executing the SQL query. Always
profile for your use case!
@@ -979,14 +1008,13 @@ of the arguments is required, but you should use at least one of them.
``select_params`` parameter. Since ``select_params`` is a sequence and
the ``select`` attribute is a dictionary, some care is required so that
the parameters are matched up correctly with the extra select pieces.
- In this situation, you should use a
- :class:`django.utils.datastructures.SortedDict` for the ``select``
- value, not just a normal Python dictionary.
+ In this situation, you should use a :class:`collections.OrderedDict` for
+ the ``select`` value, not just a normal Python dictionary.
This will work, for example::
Blog.objects.extra(
- select=SortedDict([('a', '%s'), ('b', '%s')]),
+ select=OrderedDict([('a', '%s'), ('b', '%s')]),
select_params=('one', 'two'))
The only thing to be careful about when using select parameters in
@@ -1264,6 +1292,28 @@ unexpectedly blocking.
Using ``select_for_update`` on backends which do not support
``SELECT ... FOR UPDATE`` (such as SQLite) will have no effect.
+raw
+~~~
+
+.. method:: raw(raw_query, params=None, translations=None)
+
+.. versionchanged:: 1.7
+
+ ``raw`` was moved to the ``QuerySet`` class. It was previously only on
+ :class:`~django.db.models.Manager`.
+
+Takes a raw SQL query, executes it, and returns a
+``django.db.models.query.RawQuerySet`` instance. This ``RawQuerySet`` instance
+can be iterated over just like an normal ``QuerySet`` to provide object instances.
+
+See the :ref:`executing-raw-queries` for more information.
+
+.. warning::
+
+ ``raw()`` always triggers a new query and doesn't account for previous
+ filtering. As such, it should generally be called from the ``Manager`` or
+ from a fresh ``QuerySet`` instance.
+
Methods that do not return QuerySets
------------------------------------
@@ -1866,6 +1916,17 @@ DO_NOTHING do not prevent taking the fast-path in deletion.
Note that the queries generated in object deletion is an implementation
detail subject to change.
+as_manager
+~~~~~~~~~~
+
+.. classmethod:: as_manager()
+
+.. versionadded:: 1.7
+
+Class method that returns an instance of :class:`~django.db.models.Manager`
+with a copy of the ``QuerySet``’s methods. See
+:ref:`create-manager-with-queryset-methods` for more details.
+
.. _field-lookups:
Field lookups
diff --git a/docs/ref/request-response.txt b/docs/ref/request-response.txt
index 060ec02e91..c57a1470d6 100644
--- a/docs/ref/request-response.txt
+++ b/docs/ref/request-response.txt
@@ -495,6 +495,26 @@ In addition, ``QueryDict`` has the following methods:
>>> q.lists()
[(u'a', [u'1', u'2', u'3'])]
+.. method:: QueryDict.pop(key)
+
+ Returns a list of values for the given key and removes them from the
+ dictionary. Raises ``KeyError`` if the key does not exist. For example::
+
+ >>> q = QueryDict('a=1&a=2&a=3', mutable=True)
+ >>> q.pop('a')
+ [u'1', u'2', u'3']
+
+.. method:: QueryDict.popitem()
+
+ Removes an arbitrary member of the dictionary (since there's no concept
+ of ordering), and returns a two value tuple containing the key and a list
+ of all values for the key. Raises ``KeyError`` when called on an empty
+ dictionary. For example::
+
+ >>> q = QueryDict('a=1&a=2&a=3', mutable=True)
+ >>> q.popitem()
+ (u'a', [u'1', u'2', u'3'])
+
.. method:: QueryDict.dict()
Returns ``dict`` representation of ``QueryDict``. For every (key, list)
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt
index c970311342..38d7275aed 100644
--- a/docs/ref/settings.txt
+++ b/docs/ref/settings.txt
@@ -1744,7 +1744,7 @@ Default::
A tuple of template loader classes, specified as strings. Each ``Loader`` class
knows how to import templates from a particular source. Optionally, a tuple can be
-used instead of a string. The first item in the tuple should be the ``Loader``'s
+used instead of a string. The first item in the tuple should be the ``Loader``’s
module, subsequent items are passed to the ``Loader`` during initialization. See
:doc:`/ref/templates/api`.
@@ -2478,7 +2478,7 @@ files</howto/static-files/index>` for more details about usage.
your static files from their permanent locations into one directory for
ease of deployment; it is **not** a place to store your static files
permanently. You should do that in directories that will be found by
- :doc:`staticfiles</ref/contrib/staticfiles>`'s
+ :doc:`staticfiles</ref/contrib/staticfiles>`’s
:setting:`finders<STATICFILES_FINDERS>`, which by default, are
``'static/'`` app sub-directories and any directories you include in
:setting:`STATICFILES_DIRS`).
diff --git a/docs/ref/templates/api.txt b/docs/ref/templates/api.txt
index f7dd0121d1..87822fe7f8 100644
--- a/docs/ref/templates/api.txt
+++ b/docs/ref/templates/api.txt
@@ -708,7 +708,7 @@ class. Here are the template loaders that come with Django:
with your own ``admin/base_site.html`` in ``myproject.polls``. You must
then make sure that your ``myproject.polls`` comes *before*
``django.contrib.admin`` in :setting:`INSTALLED_APPS`, otherwise
- ``django.contrib.admin``'s will be loaded first and yours will be ignored.
+ ``django.contrib.admin``’s will be loaded first and yours will be ignored.
Note that the loader performs an optimization when it is first imported:
it caches a list of which :setting:`INSTALLED_APPS` packages have a
diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
index 6b614e0c83..d31de35006 100644
--- a/docs/ref/utils.txt
+++ b/docs/ref/utils.txt
@@ -105,6 +105,10 @@ to distinguish caches by the ``Accept-language`` header.
.. class:: SortedDict
+.. deprecated:: 1.7
+ ``SortedDict`` is deprecated and will be removed in Django 1.9. Use
+ :class:`collections.OrderedDict` instead.
+
The :class:`django.utils.datastructures.SortedDict` class is a dictionary
that keeps its keys in the order in which they're inserted.
@@ -427,6 +431,64 @@ Atom1Feed
.. module:: django.utils.functional
:synopsis: Functional programming tools.
+.. class:: cached_property(object)
+
+ The ``@cached_property`` decorator caches the result of a method with a
+ single ``self`` argument as a property. The cached result will persist
+ as long as the instance does, so if the instance is passed around and the
+ function subsequently invoked, the cached result will be returned.
+
+ Consider a typical case, where a view might need to call a model's method
+ to perform some computation, before placing the model instance into the
+ context, where the template might invoke the method once more::
+
+ # the model
+ class Person(models.Model):
+
+ def friends(self):
+ # expensive computation
+ ...
+ return friends
+
+ # in the view:
+ if person.friends():
+
+ # in the template:
+ {% for friend in person.friends %}
+
+ Here, ``friends()`` will be called twice. Since the instance ``person`` in
+ the view and the template are the same, ``@cached_property`` can avoid
+ that::
+
+ from django.utils.functional import cached_property
+
+ @cached_property
+ def friends(self):
+ # expensive computation
+ ...
+ return friends
+
+ Note that as the method is now a property, in Python code it will need to
+ be invoked appropriately::
+
+ # in the view:
+ if person.friends:
+
+ The cached value can be treated like an ordinary attribute of the instance::
+
+ # clear it, requiring re-computation next time it's called
+ del person.friends # or delattr(person, "friends")
+
+ # set a value manually, that will persist on the instance until cleared
+ person.friends = ["Huckleberry Finn", "Tom Sawyer"]
+
+ As well as offering potential performance advantages, ``@cached_property``
+ can ensure that an attribute's value does not change unexpectedly over the
+ life of an instance. This could occur with a method whose computation is
+ based on ``datetime.now()``, or simply if a change were saved to the
+ database by some other process in the brief interval between subsequent
+ invocations of a method on the same instance.
+
.. function:: allow_lazy(func, *resultclasses)
Django offers many utility functions (particularly in ``django.utils``) that