mirror of
https://github.com/django/django.git
synced 2025-08-03 18:38:50 +00:00
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
This commit is contained in:
commit
de64c4d6e9
489 changed files with 3840 additions and 1593 deletions
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()`::
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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>`.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
==============
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
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
|
||||
|
||||
The :exc:`DoesNotExist` exception is raised when an object is not found
|
||||
for the given parameters of a query.
|
||||
|
||||
: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
|
||||
=================
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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``
|
||||
--------------------
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"),)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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`).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue