123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221 |
- =========================
- Django 1.6 release notes
- =========================
- .. note::
- Dedicated to Malcolm Tredinnick
- On March 17, 2013, the Django project and the free software community lost
- a very dear friend and developer.
- Malcolm was a long-time contributor to Django, a model community member, a
- brilliant mind, and a friend. His contributions to Django — and to many other
- open source projects — are nearly impossible to enumerate. Many on the core
- Django team had their first patches reviewed by him; his mentorship enriched
- us. His consideration, patience, and dedication will always be an inspiration
- to us.
- This release of Django is for Malcolm.
- -- The Django Developers
- *November 6, 2013*
- Welcome to Django 1.6!
- These release notes cover the `new features`_, as well as some `backwards
- incompatible changes`_ you'll want to be aware of when upgrading from Django
- 1.5 or older versions. We've also dropped some features, which are detailed in
- :ref:`our deprecation plan <deprecation-removed-in-1.6>`, and we've `begun the
- deprecation process for some features`_.
- .. _`new features`: `What's new in Django 1.6`_
- .. _`backwards incompatible changes`: `Backwards incompatible changes in 1.6`_
- .. _`begun the deprecation process for some features`: `Features deprecated in 1.6`_
- Python compatibility
- ====================
- Django 1.6, like Django 1.5, requires Python 2.6.5 or above. Python 3 is also
- officially supported. We **highly recommend** the latest minor release for each
- supported Python series (2.6.X, 2.7.X, 3.2.X, and 3.3.X).
- Django 1.6 will be the final release series to support Python 2.6; beginning
- with Django 1.7, the minimum supported Python version will be 2.7.
- Python 3.4 is not supported, but support will be added in Django 1.7.
- What's new in Django 1.6
- ========================
- Simplified default project and app templates
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The default templates used by :djadmin:`startproject` and :djadmin:`startapp`
- have been simplified and modernized. The :doc:`admin
- </ref/contrib/admin/index>` is now enabled by default in new projects; the
- :doc:`sites </ref/contrib/sites>` framework no longer is. :ref:`clickjacking
- prevention <clickjacking-prevention>` is now on and the database defaults to
- SQLite.
- If the default templates don't suit your tastes, you can use :ref:`custom
- project and app templates <custom-app-and-project-templates>`.
- Improved transaction management
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django's transaction management was overhauled. Database-level autocommit is
- now turned on by default. This makes transaction handling more explicit and
- should improve performance. The existing APIs were deprecated, and new APIs
- were introduced, as described in the :doc:`transaction management docs
- </topics/db/transactions>`.
- Persistent database connections
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django now supports reusing the same database connection for several requests.
- This avoids the overhead of re-establishing a connection at the beginning of
- each request. For backwards compatibility, this feature is disabled by
- default. See :ref:`persistent-database-connections` for details.
- Discovery of tests in any test module
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django 1.6 ships with a new test runner that allows more flexibility in the
- location of tests. The previous runner
- (``django.test.simple.DjangoTestSuiteRunner``) found tests only in the
- ``models.py`` and ``tests.py`` modules of a Python package in
- :setting:`INSTALLED_APPS`.
- The new runner (``django.test.runner.DiscoverRunner``) uses the test discovery
- features built into ``unittest2`` (the version of ``unittest`` in the
- Python 2.7+ standard library, and bundled with Django). With test discovery,
- tests can be located in any module whose name matches the pattern ``test*.py``.
- In addition, the test labels provided to ``./manage.py test`` to nominate
- specific tests to run must now be full Python dotted paths (or directory
- paths), rather than ``applabel.TestCase.test_method_name`` pseudo-paths. This
- allows running tests located anywhere in your codebase, rather than only in
- :setting:`INSTALLED_APPS`. For more details, see :doc:`/topics/testing/index`.
- This change is backwards-incompatible; see the :ref:`backwards-incompatibility
- notes<new-test-runner>`.
- Time zone aware aggregation
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The support for :doc:`time zones </topics/i18n/timezones>` introduced in
- Django 1.4 didn't work well with :meth:`QuerySet.dates()
- <django.db.models.query.QuerySet.dates>`: aggregation was always performed in
- UTC. This limitation was lifted in Django 1.6. Use :meth:`QuerySet.datetimes()
- <django.db.models.query.QuerySet.datetimes>` to perform time zone aware
- aggregation on a :class:`~django.db.models.DateTimeField`.
- Support for savepoints in SQLite
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django 1.6 adds support for savepoints in SQLite, with some :ref:`limitations
- <savepoints-in-sqlite>`.
- ``BinaryField`` model field
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A new :class:`django.db.models.BinaryField` model field allows storage of raw
- binary data in the database.
- GeoDjango form widgets
- ~~~~~~~~~~~~~~~~~~~~~~
- GeoDjango now provides :doc:`form fields and widgets </ref/contrib/gis/forms-api>`
- for its geo-specialized fields. They are OpenLayers-based by default, but they
- can be customized to use any other JS framework.
- ``check`` management command added for verifying compatibility
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- A :djadmin:`check` management command was added, enabling you to verify if your
- current configuration (currently oriented at settings) is compatible with the
- current version of Django.
- :meth:`Model.save() <django.db.models.Model.save()>` algorithm changed
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The :meth:`Model.save() <django.db.models.Model.save()>` method now
- tries to directly ``UPDATE`` the database if the instance has a primary
- key value. Previously ``SELECT`` was performed to determine if ``UPDATE``
- or ``INSERT`` were needed. The new algorithm needs only one query for
- updating an existing row while the old algorithm needed two. See
- :meth:`Model.save() <django.db.models.Model.save()>` for more details.
- In some rare cases the database doesn't report that a matching row was
- found when doing an ``UPDATE``. An example is the PostgreSQL ``ON UPDATE``
- trigger which returns ``NULL``. In such cases it is possible to set
- :attr:`django.db.models.Options.select_on_save` flag to force saving to
- use the old algorithm.
- Minor features
- ~~~~~~~~~~~~~~
- * Authentication backends can raise ``PermissionDenied`` to immediately fail
- the authentication chain.
- * The ``HttpOnly`` flag can be set on the CSRF cookie with
- :setting:`CSRF_COOKIE_HTTPONLY`.
- * The :meth:`~django.test.TransactionTestCase.assertQuerysetEqual` now checks
- for undefined order and raises :exc:`ValueError` if undefined
- order is spotted. The order is seen as undefined if the given ``QuerySet``
- isn't ordered and there are more than one ordered values to compare against.
- * Added :meth:`~django.db.models.query.QuerySet.earliest` for symmetry with
- :meth:`~django.db.models.query.QuerySet.latest`.
- * In addition to :lookup:`year`, :lookup:`month` and :lookup:`day`, the ORM
- now supports :lookup:`hour`, :lookup:`minute` and :lookup:`second` lookups.
- * Django now wraps all PEP-249 exceptions.
- * The default widgets for :class:`~django.forms.EmailField`,
- :class:`~django.forms.URLField`, :class:`~django.forms.IntegerField`,
- :class:`~django.forms.FloatField` and :class:`~django.forms.DecimalField` use
- the new type attributes available in HTML5 (``type='email'``, ``type='url'``,
- ``type='number'``). Note that due to erratic support of the ``number``
- input type with localized numbers in current browsers, Django only uses it
- when numeric fields are not localized.
- * The ``number`` argument for :ref:`lazy plural translations
- <lazy-plural-translations>` can be provided at translation time rather than
- at definition time.
- * For custom management commands: Verification of the presence of valid
- settings in commands that ask for it by using the
- :attr:`~django.core.management.BaseCommand.can_import_settings` internal
- option is now performed independently from handling of the locale that
- should be active during the execution of the command. The latter can now be
- influenced by the new
- :attr:`~django.core.management.BaseCommand.leave_locale_alone` internal
- option. See :ref:`management-commands-and-locales` for more details.
- * The :attr:`~django.views.generic.edit.DeletionMixin.success_url` of
- :class:`~django.views.generic.edit.DeletionMixin` is now interpolated with
- its ``object``’s ``__dict__``.
- * :class:`~django.http.HttpResponseRedirect` and
- :class:`~django.http.HttpResponsePermanentRedirect` now provide an ``url``
- attribute (equivalent to the URL the response will redirect to).
- * The ``MemcachedCache`` cache backend now uses the latest :mod:`pickle`
- protocol available.
- * Added :class:`~django.contrib.messages.views.SuccessMessageMixin` which
- provides a ``success_message`` attribute for
- :class:`~django.views.generic.edit.FormView` based classes.
- * Added the :attr:`django.db.models.ForeignKey.db_constraint` and
- :attr:`django.db.models.ManyToManyField.db_constraint` options.
- * The jQuery library embedded in the admin has been upgraded to version 1.9.1.
- * Syndication feeds (:mod:`django.contrib.syndication`) can now pass extra
- context through to feed templates using a new
- :meth:`Feed.get_context_data()
- <django.contrib.syndication.Feed.get_context_data>` callback.
- * The admin list columns have a ``column-<field_name>`` class in the HTML
- so the columns header can be styled with CSS, e.g. to set a column width.
- * The :ref:`isolation level<database-isolation-level>` can be customized under
- PostgreSQL.
- * The :ttag:`blocktrans` template tag now respects
- ``TEMPLATE_STRING_IF_INVALID`` for variables not present in the
- context, just like other template constructs.
- * ``SimpleLazyObject``\s will now present more helpful representations in shell
- debugging situations.
- * Generic :class:`~django.contrib.gis.db.models.GeometryField` is now editable
- with the OpenLayers widget in the admin.
- * The documentation contains a :doc:`deployment checklist
- </howto/deployment/checklist>`.
- * The :djadmin:`diffsettings` command gained a ``--all`` option.
- * ``django.forms.fields.Field.__init__`` now calls ``super()``, allowing
- field mixins to implement ``__init__()`` methods that will reliably be
- called.
- * The ``validate_max`` parameter was added to ``BaseFormSet`` and
- :func:`~django.forms.formsets.formset_factory`, and ``ModelForm`` and inline
- versions of the same. The behavior of validation for formsets with
- ``max_num`` was clarified. The previously undocumented behavior that
- hardened formsets against memory exhaustion attacks was documented,
- and the undocumented limit of the higher of 1000 or ``max_num`` forms
- was changed so it is always 1000 more than ``max_num``.
- * Added ``BCryptSHA256PasswordHasher`` to resolve the password truncation issue
- with bcrypt.
- * `Pillow`_ is now the preferred image manipulation library to use with Django.
- `PIL`_ is pending deprecation (support to be removed in Django 1.8).
- To upgrade, you should **first** uninstall PIL, **then** install Pillow.
- .. _`Pillow`: https://pypi.python.org/pypi/Pillow
- .. _`PIL`: https://pypi.python.org/pypi/PIL
- * :class:`~django.forms.ModelForm` accepts several new ``Meta``
- options.
- * Fields included in the ``localized_fields`` list will be localized
- (by setting ``localize`` on the form field).
- * The ``labels``, ``help_texts`` and ``error_messages`` options may be used
- to customize the default fields, see
- :ref:`modelforms-overriding-default-fields` for details.
- * The ``choices`` argument to model fields now accepts an iterable of iterables
- instead of requiring an iterable of lists or tuples.
- * The reason phrase can be customized in HTTP responses using
- :attr:`~django.http.HttpResponse.reason_phrase`.
- * When giving the URL of the next page for
- :func:`~django.contrib.auth.views.logout`,
- :func:`~django.contrib.auth.views.password_reset`,
- :func:`~django.contrib.auth.views.password_reset_confirm`,
- and :func:`~django.contrib.auth.views.password_change`, you can now pass
- URL names and they will be resolved.
- * The :djadmin:`dumpdata` ``manage.py`` command now has a :djadminopt:`--pks`
- option which will allow users to specify the primary keys of objects they
- want to dump. This option can only be used with one model.
- * Added ``QuerySet`` methods :meth:`~django.db.models.query.QuerySet.first`
- and :meth:`~django.db.models.query.QuerySet.last` which are convenience
- methods returning the first or last object matching the filters. Returns
- ``None`` if there are no objects matching.
- * :class:`~django.views.generic.base.View` and
- :class:`~django.views.generic.base.RedirectView` now support HTTP ``PATCH``
- method.
- * ``GenericForeignKey`` now takes an optional ``for_concrete_model`` argument,
- which when set to ``False`` allows the field to reference proxy models. The
- default is ``True`` to retain the old behavior.
- * The :class:`~django.middleware.locale.LocaleMiddleware` now stores the active
- language in session if it is not present there. This prevents loss of
- language settings after session flush, e.g. logout.
- * :exc:`~django.core.exceptions.SuspiciousOperation` has been differentiated
- into a number of subclasses, and each will log to a matching named logger
- under the ``django.security`` logging hierarchy. Along with this change,
- a ``handler400`` mechanism and default view are used whenever
- a ``SuspiciousOperation`` reaches the WSGI handler to return an
- ``HttpResponseBadRequest``.
- * The :exc:`~django.core.exceptions.DoesNotExist` exception now includes a
- message indicating the name of the attribute used for the lookup.
- * The :meth:`~django.db.models.query.QuerySet.get_or_create` method no longer
- requires at least one keyword argument.
- * The :class:`~django.test.SimpleTestCase` class includes a new assertion
- helper for testing formset errors:
- :meth:`~django.test.SimpleTestCase.assertFormsetError`.
- * The list of related fields added to a
- :class:`~django.db.models.query.QuerySet` by
- :meth:`~django.db.models.query.QuerySet.select_related` can be cleared using
- ``select_related(None)``.
- * The :meth:`~django.contrib.admin.InlineModelAdmin.get_extra` and
- :meth:`~django.contrib.admin.InlineModelAdmin.get_max_num` methods on
- :class:`~django.contrib.admin.InlineModelAdmin` may be overridden to
- customize the extra and maximum number of inline forms.
- * Formsets now have a
- :meth:`~django.forms.formsets.BaseFormSet.total_error_count` method.
- * :class:`~django.forms.ModelForm` fields can now override error messages
- defined in model fields by using the
- :attr:`~django.forms.Field.error_messages` argument of a ``Field``’s
- constructor. To take advantage of this new feature with your custom fields,
- :ref:`see the updated recommendation <raising-validation-error>` for raising
- a ``ValidationError``.
- * :class:`~django.contrib.admin.ModelAdmin` now preserves filters on the list view
- after creating, editing or deleting an object. It's possible to restore the previous
- behavior of clearing filters by setting the
- :attr:`~django.contrib.admin.ModelAdmin.preserve_filters` attribute to ``False``.
- * Added
- :meth:`FormMixin.get_prefix<django.views.generic.edit.FormMixin.get_prefix>`
- (which returns
- :attr:`FormMixin.prefix<django.views.generic.edit.FormMixin.prefix>` by
- default) to allow customizing the :attr:`~django.forms.Form.prefix` of the
- form.
- * Raw queries (``Manager.raw()`` or ``cursor.execute()``) can now use the
- "pyformat" parameter style, where placeholders in the query are given as
- ``'%(name)s'`` and the parameters are passed as a dictionary rather than
- a list (except on SQLite). This has long been possible (but not officially
- supported) on MySQL and PostgreSQL, and is now also available on Oracle.
- * The default iteration count for the PBKDF2 password hasher has been
- increased by 20%. This backwards compatible change will not affect
- existing passwords or users who have subclassed
- ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
- default value. Passwords :ref:`will be upgraded <password-upgrades>` to use
- the new iteration count as necessary.
- Backwards incompatible changes in 1.6
- =====================================
- .. warning::
- In addition to the changes outlined in this section, be sure to review the
- :ref:`deprecation plan <deprecation-removed-in-1.6>` for any features that
- have been removed. If you haven't updated your code within the
- deprecation timeline for a given feature, its removal may appear as a
- backwards incompatible change.
- New transaction management model
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Behavior changes
- ^^^^^^^^^^^^^^^^
- Database-level autocommit is enabled by default in Django 1.6. While this
- doesn't change the general spirit of Django's transaction management, there
- are a few backwards-incompatibilities.
- Savepoints and ``assertNumQueries``
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The changes in transaction management may result in additional statements to
- create, release or rollback savepoints. This is more likely to happen with
- SQLite, since it didn't support savepoints until this release.
- If tests using :meth:`~django.test.TransactionTestCase.assertNumQueries` fail
- because of a higher number of queries than expected, check that the extra
- queries are related to savepoints, and adjust the expected number of queries
- accordingly.
- Autocommit option for PostgreSQL
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- In previous versions, database-level autocommit was only an option for
- PostgreSQL, and it was disabled by default. This option is now ignored and can
- be removed.
- .. _new-test-runner:
- New test runner
- ~~~~~~~~~~~~~~~
- In order to maintain greater consistency with Python's unittest module, the new
- test runner (``django.test.runner.DiscoverRunner``) does not automatically
- support some types of tests that were supported by the previous runner:
- * Tests in ``models.py`` and ``tests/__init__.py`` files will no longer be
- found and run. Move them to a file whose name begins with ``test``.
- * Doctests will no longer be automatically discovered. To integrate doctests in
- your test suite, follow the `recommendations in the Python documentation`_.
- Django bundles a modified version of the :mod:`doctest` module from the Python
- standard library (in ``django.test._doctest``) and includes some additional
- doctest utilities. These utilities are deprecated and will be removed in Django
- 1.8; doctest suites should be updated to work with the standard library's
- doctest module (or converted to unittest-compatible tests).
- If you wish to delay updates to your test suite, you can set your
- :setting:`TEST_RUNNER` setting to ``django.test.simple.DjangoTestSuiteRunner``
- to fully restore the old test behavior. ``DjangoTestSuiteRunner`` is deprecated
- but will not be removed from Django until version 1.8.
- .. _recommendations in the Python documentation: https://docs.python.org/library/doctest.html#unittest-api
- Removal of ``django.contrib.gis.tests.GeoDjangoTestSuiteRunner`` GeoDjango custom test runner
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- This is for developers working on the GeoDjango application itself and related
- to the item above about changes in the test runners:
- The ``django.contrib.gis.tests.GeoDjangoTestSuiteRunner`` test runner has been
- removed and the standalone GeoDjango tests execution setup it implemented isn't
- supported anymore. To run the GeoDjango tests simply use the new
- ``DiscoverRunner`` and specify the ``django.contrib.gis`` app.
- Custom User models in tests
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The introduction of the new test runner has also slightly changed the way that
- test models are imported. As a result, any test that overrides ``AUTH_USER_MODEL``
- to test behavior with one of Django's test user models (
- :class:`~django.contrib.auth.tests.custom_user.CustomUser` and
- :class:`~django.contrib.auth.tests.custom_user.ExtensionUser`) must now
- explicitly import the User model in your test module::
- from django.contrib.auth.tests.custom_user import CustomUser
- @override_settings(AUTH_USER_MODEL='auth.CustomUser')
- class CustomUserFeatureTests(TestCase):
- def test_something(self):
- # Test code here ...
- This import forces the custom user model to be registered. Without this import,
- the test will be unable to swap in the custom user model, and you will get an
- error reporting::
- ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed
- Time zone-aware ``day``, ``month``, and ``week_day`` lookups
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django 1.6 introduces time zone support for :lookup:`day`, :lookup:`month`,
- and :lookup:`week_day` lookups when :setting:`USE_TZ` is ``True``. These
- lookups were previously performed in UTC regardless of the current time zone.
- This requires :ref:`time zone definitions in the database
- <database-time-zone-definitions>`. If you're using SQLite, you must install
- pytz_. If you're using MySQL, you must install pytz_ and load the time zone
- tables with `mysql_tzinfo_to_sql`_.
- .. _pytz: http://pytz.sourceforge.net/
- .. _mysql_tzinfo_to_sql: http://dev.mysql.com/doc/refman/5.6/en/mysql-tzinfo-to-sql.html
- Addition of ``QuerySet.datetimes()``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- When the :doc:`time zone support </topics/i18n/timezones>` added in Django 1.4
- was active, :meth:`QuerySet.dates() <django.db.models.query.QuerySet.dates>`
- lookups returned unexpected results, because the aggregation was performed in
- UTC. To fix this, Django 1.6 introduces a new API, :meth:`QuerySet.datetimes()
- <django.db.models.query.QuerySet.datetimes>`. This requires a few changes in
- your code.
- ``QuerySet.dates()`` returns ``date`` objects
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :meth:`QuerySet.dates() <django.db.models.query.QuerySet.dates>` now returns a
- list of :class:`~datetime.date`. It used to return a list of
- :class:`~datetime.datetime`.
- :meth:`QuerySet.datetimes() <django.db.models.query.QuerySet.datetimes>`
- returns a list of :class:`~datetime.datetime`.
- ``QuerySet.dates()`` no longer usable on ``DateTimeField``
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :meth:`QuerySet.dates() <django.db.models.query.QuerySet.dates>` raises an
- error if it's used on :class:`~django.db.models.DateTimeField` when time
- zone support is active. Use :meth:`QuerySet.datetimes()
- <django.db.models.query.QuerySet.datetimes>` instead.
- ``date_hierarchy`` requires time zone definitions
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- The :attr:`~django.contrib.admin.ModelAdmin.date_hierarchy` feature of the
- admin now relies on :meth:`QuerySet.datetimes()
- <django.db.models.query.QuerySet.datetimes>` when it's used on a
- :class:`~django.db.models.DateTimeField`.
- This requires time zone definitions in the database when :setting:`USE_TZ` is
- ``True``. :ref:`Learn more <database-time-zone-definitions>`.
- ``date_list`` in generic views requires time zone definitions
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- For the same reason, accessing ``date_list`` in the context of a date-based
- generic view requires time zone definitions in the database when the view is
- based on a :class:`~django.db.models.DateTimeField` and :setting:`USE_TZ` is
- ``True``. :ref:`Learn more <database-time-zone-definitions>`.
- New lookups may clash with model fields
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django 1.6 introduces ``hour``, ``minute``, and ``second`` lookups on
- :class:`~django.db.models.DateTimeField`. If you had model fields called
- ``hour``, ``minute``, or ``second``, the new lookups will clash with you field
- names. Append an explicit :lookup:`exact` lookup if this is an issue.
- ``BooleanField`` no longer defaults to ``False``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- When a :class:`~django.db.models.BooleanField` doesn't have an explicit
- :attr:`~django.db.models.Field.default`, the implicit default value is
- ``None``. In previous version of Django, it was ``False``, but that didn't
- represent accurately the lack of a value.
- Code that relies on the default value being ``False`` may raise an exception
- when saving new model instances to the database, because ``None`` isn't an
- acceptable value for a :class:`~django.db.models.BooleanField`. You should
- either specify ``default=False`` in the field definition, or ensure the field
- is set to ``True`` or ``False`` before saving the object.
- Translations and comments in templates
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Extraction of translations after comments
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Extraction of translatable literals from templates with the
- :djadmin:`makemessages` command now correctly detects i18n constructs when
- they are located after a ``{#`` / ``#}``-type comment on the same line. E.g.:
- .. code-block:: html+django
- {# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}
- Location of translator comments
- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- :ref:`translator-comments-in-templates` specified using ``{#`` / ``#}`` need to
- be at the end of a line. If they are not, the comments are ignored and
- :djadmin:`makemessages` will generate a warning. For example:
- .. code-block:: html+django
- {# Translators: This is ignored #}{% trans "Translate me" %}
- {{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
- <h1>{% trans "Welcome" %}</h1>
- Quoting in :func:`~django.core.urlresolvers.reverse`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- When reversing URLs, Django didn't apply :func:`~django.utils.http.urlquote`
- to arguments before interpolating them in URL patterns. This bug is fixed in
- Django 1.6. If you worked around this bug by applying URL quoting before
- passing arguments to :func:`~django.core.urlresolvers.reverse`, this may
- result in double-quoting. If this happens, simply remove the URL quoting from
- your code. You will also have to replace special characters in URLs used in
- :func:`~django.test.SimpleTestCase.assertRedirects` with their encoded versions.
- Storage of IP addresses in the comments app
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The comments app now uses a
- ``GenericIPAddressField`` for storing commenters' IP addresses, to support
- comments submitted from IPv6 addresses. Until now, it stored them in an
- ``IPAddressField``, which is only meant to support IPv4. When saving a comment
- made from an IPv6 address, the address would be silently truncated on MySQL
- databases, and raise an exception on Oracle. You will need to change the
- column type in your database to benefit from this change.
- For MySQL, execute this query on your project's database:
- .. code-block:: sql
- ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);
- For Oracle, execute this query:
- .. code-block:: sql
- ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));
- If you do not apply this change, the behavior is unchanged: on MySQL, IPv6
- addresses are silently truncated; on Oracle, an exception is generated. No
- database change is needed for SQLite or PostgreSQL databases.
- Percent literals in ``cursor.execute`` queries
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- When you are running raw SQL queries through the
- :ref:`cursor.execute <executing-custom-sql>` method, the rule about doubling
- percent literals (``%``) inside the query has been unified. Past behavior
- depended on the database backend. Now, across all backends, you only need to
- double literal percent characters if you are also providing replacement
- parameters. For example::
- # No parameters, no percent doubling
- cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
- # Parameters passed, non-placeholders have to be doubled
- cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])
- ``SQLite`` users need to check and update such queries.
- .. _m2m-help_text:
- Help text of model form fields for ManyToManyField fields
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- HTML rendering of model form fields corresponding to
- :class:`~django.db.models.ManyToManyField` model fields used to get the
- hard-coded sentence:
- *Hold down "Control", or "Command" on a Mac, to select more than one.*
- (or its translation to the active locale) imposed as the help legend shown along
- them if neither :attr:`model <django.db.models.Field.help_text>` nor :attr:`form
- <django.forms.Field.help_text>` ``help_text`` attributes were specified by the
- user (or this string was appended to any ``help_text`` that was provided).
- Since this happened at the model layer, there was no way to prevent the text
- from appearing in cases where it wasn't applicable such as form fields that
- implement user interactions that don't involve a keyboard and/or a mouse.
- Starting with Django 1.6, as an ad-hoc temporary backward-compatibility
- provision, the logic to add the "Hold down..." sentence has been moved to the
- model form field layer and modified to add the text only when the associated
- widget is :class:`~django.forms.SelectMultiple` or selected subclasses.
- The change can affect you in a backward incompatible way if you employ custom
- model form fields and/or widgets for ``ManyToManyField`` model fields whose UIs
- do rely on the automatic provision of the mentioned hard-coded sentence. These
- form field implementations need to adapt to the new scenario by providing their
- own handling of the ``help_text`` attribute.
- Applications that use Django :doc:`model form </topics/forms/modelforms>`
- facilities together with Django built-in form :doc:`fields </ref/forms/fields>`
- and :doc:`widgets </ref/forms/widgets>` aren't affected but need to be aware of
- what's described in :ref:`m2m-help_text-deprecation` below.
- QuerySet iteration
- ~~~~~~~~~~~~~~~~~~
- The ``QuerySet`` iteration was changed to immediately convert all fetched
- rows to ``Model`` objects. In Django 1.5 and earlier the fetched rows were
- converted to ``Model`` objects in chunks of 100.
- Existing code will work, but the amount of rows converted to objects
- might change in certain use cases. Such usages include partially looping
- over a queryset or any usage which ends up doing ``__bool__`` or
- ``__contains__``.
- Notably most database backends did fetch all the rows in one go already in
- 1.5.
- It is still possible to convert the fetched rows to ``Model`` objects
- lazily by using the :meth:`~django.db.models.query.QuerySet.iterator()`
- method.
- :meth:`BoundField.label_tag<django.forms.BoundField.label_tag>` now includes the form's :attr:`~django.forms.Form.label_suffix`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- This is consistent with how methods like
- :meth:`Form.as_p<django.forms.Form.as_p>` and
- :meth:`Form.as_ul<django.forms.Form.as_ul>` render labels.
- If you manually render ``label_tag`` in your templates:
- .. code-block:: html+django
- {{ form.my_field.label_tag }}: {{ form.my_field }}
- you'll want to remove the colon (or whatever other separator you may be
- using) to avoid duplicating it when upgrading to Django 1.6. The following
- template in Django 1.6 will render identically to the above template in Django
- 1.5, except that the colon will appear inside the ``<label>`` element.
- .. code-block:: html+django
- {{ form.my_field.label_tag }} {{ form.my_field }}
- will render something like:
- .. code-block:: html
- <label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />
- If you want to keep the current behavior of rendering ``label_tag`` without
- the ``label_suffix``, instantiate the form ``label_suffix=''``. You can also
- customize the ``label_suffix`` on a per-field basis using the new
- ``label_suffix`` parameter on :meth:`~django.forms.BoundField.label_tag`.
- Admin views ``_changelist_filters`` GET parameter
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- To achieve preserving and restoring list view filters, admin views now
- pass around the `_changelist_filters` GET parameter. It's important that you
- account for that change if you have custom admin templates or if your tests
- rely on the previous URLs. If you want to revert to the original behavior you
- can set the
- :attr:`~django.contrib.admin.ModelAdmin.preserve_filters` attribute to ``False``.
- ``django.contrib.auth`` password reset uses base 64 encoding of ``User`` PK
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Past versions of Django used base 36 encoding of the ``User`` primary key in
- the password reset views and URLs
- (:func:`django.contrib.auth.views.password_reset_confirm`). Base 36 encoding is
- sufficient if the user primary key is an integer, however, with the
- introduction of custom user models in Django 1.5, that assumption may no longer
- be true.
- :func:`django.contrib.auth.views.password_reset_confirm` has been modified to
- take a ``uidb64`` parameter instead of ``uidb36``. If you are reversing this
- view, for example in a custom ``password_reset_email.html`` template, be sure
- to update your code.
- A temporary shim for :func:`django.contrib.auth.views.password_reset_confirm`
- that will allow password reset links generated prior to Django 1.6 to continue
- to work has been added to provide backwards compatibility; this will be removed
- in Django 1.7. Thus, as long as your site has been running Django 1.6 for more
- than :setting:`PASSWORD_RESET_TIMEOUT_DAYS`, this change will have no effect.
- If not (for example, if you upgrade directly from Django 1.5 to Django 1.7),
- then any password reset links generated before you upgrade to Django 1.7 or
- later won't work after the upgrade.
- In addition, if you have any custom password reset URLs, you will need to
- update them by replacing ``uidb36`` with ``uidb64`` and the dash that follows
- that pattern with a slash. Also add ``_\-`` to the list of characters that may
- match the ``uidb64`` pattern.
- For example::
- url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
- 'django.contrib.auth.views.password_reset_confirm',
- name='password_reset_confirm'),
- becomes::
- url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$',
- 'django.contrib.auth.views.password_reset_confirm',
- name='password_reset_confirm'),
- You may also want to add the shim to support the old style reset links. Using
- the example above, you would modify the existing url by replacing
- ``django.contrib.auth.views.password_reset_confirm`` with
- ``django.contrib.auth.views.password_reset_confirm_uidb36`` and also remove
- the ``name`` argument so it doesn't conflict with the new url::
- url(r'^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
- 'django.contrib.auth.views.password_reset_confirm_uidb36'),
- You can remove this url pattern after your app has been deployed with Django
- 1.6 for :setting:`PASSWORD_RESET_TIMEOUT_DAYS`.
- Default session serialization switched to JSON
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Historically, :mod:`django.contrib.sessions` used :mod:`pickle` to serialize
- session data before storing it in the backend. If you're using the :ref:`signed
- cookie session backend<cookie-session-backend>` and :setting:`SECRET_KEY` is
- known by an attacker (there isn't an inherent vulnerability in Django that
- would cause it to leak), the attacker could insert a string into his session
- which, when unpickled, executes arbitrary code on the server. The technique for
- doing so is simple and easily available on the internet. Although the cookie
- session storage signs the cookie-stored data to prevent tampering, a
- :setting:`SECRET_KEY` leak immediately escalates to a remote code execution
- vulnerability.
- This attack can be mitigated by serializing session data using JSON rather
- than :mod:`pickle`. To facilitate this, Django 1.5.3 introduced a new setting,
- :setting:`SESSION_SERIALIZER`, to customize the session serialization format.
- For backwards compatibility, this setting defaulted to using :mod:`pickle`
- in Django 1.5.3, but we've changed the default to JSON in 1.6. If you upgrade
- and switch from pickle to JSON, sessions created before the upgrade will be
- lost. While JSON serialization does not support all Python objects like
- :mod:`pickle` does, we highly recommend using JSON-serialized sessions. Be
- aware of the following when checking your code to determine if JSON
- serialization will work for your application:
- * JSON requires string keys, so you will likely run into problems if you are
- using non-string keys in ``request.session``.
- * Setting session expiration by passing ``datetime`` values to
- :meth:`~django.contrib.sessions.backends.base.SessionBase.set_expiry` will
- not work as ``datetime`` values are not serializable in JSON. You can use
- integer values instead.
- See the :ref:`session_serialization` documentation for more details.
- Object Relational Mapper changes
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django 1.6 contains many changes to the ORM. These changes fall mostly in
- three categories:
- 1. Bug fixes (e.g. proper join clauses for generic relations, query combining,
- join promotion, and join trimming fixes)
- 2. Preparation for new features. For example the ORM is now internally ready
- for multicolumn foreign keys.
- 3. General cleanup.
- These changes can result in some compatibility problems. For example, some
- queries will now generate different table aliases. This can affect
- :meth:`QuerySet.extra() <django.db.models.query.QuerySet.extra>`. In addition
- some queries will now produce different results. An example is
- :meth:`exclude(condition) <django.db.models.query.QuerySet.exclude>`
- where the condition is a complex one (referencing multijoins inside
- :class:`Q objects <django.db.models.Q>`). In many cases the affected
- queries didn't produce correct results in Django 1.5 but do now.
- Unfortunately there are also cases that produce different results, but
- neither Django 1.5 nor 1.6 produce correct results.
- Finally, there have been many changes to the ORM internal APIs.
- Miscellaneous
- ~~~~~~~~~~~~~
- * The ``django.db.models.query.EmptyQuerySet`` can't be instantiated any more -
- it is only usable as a marker class for checking if
- :meth:`~django.db.models.query.QuerySet.none` has been called:
- ``isinstance(qs.none(), EmptyQuerySet)``
- * If your CSS/Javascript code used to access HTML input widgets by type, you
- should review it as ``type='text'`` widgets might be now output as
- ``type='email'``, ``type='url'`` or ``type='number'`` depending on their
- corresponding field type.
- * Form field's :attr:`~django.forms.Field.error_messages` that contain a
- placeholder should now always use a named placeholder (``"Value '%(value)s' is
- too big"`` instead of ``"Value '%s' is too big"``). See the corresponding
- field documentation for details about the names of the placeholders. The
- changes in 1.6 particularly affect :class:`~django.forms.DecimalField` and
- :class:`~django.forms.ModelMultipleChoiceField`.
- * Some :attr:`~django.forms.Field.error_messages` for
- :class:`~django.forms.IntegerField`, :class:`~django.forms.EmailField`,
- ``IPAddressField``, :class:`~django.forms.GenericIPAddressField`, and
- :class:`~django.forms.SlugField` have been suppressed because they
- duplicated error messages already provided by validators tied to the fields.
- * Due to a change in the form validation workflow,
- :class:`~django.forms.TypedChoiceField` ``coerce`` method should always
- return a value present in the ``choices`` field attribute. That limitation
- should be lift again in Django 1.7.
- * There have been changes in the way timeouts are handled in cache backends.
- Explicitly passing in ``timeout=None`` no longer results in using the
- default timeout. It will now set a non-expiring timeout. Passing 0 into the
- memcache backend no longer uses the default timeout, and now will
- set-and-expire-immediately the value.
- * The ``django.contrib.flatpages`` app used to set custom HTTP headers for
- debugging purposes. This functionality was not documented and made caching
- ineffective so it has been removed, along with its generic implementation,
- previously available in ``django.core.xheaders``.
- * The ``XViewMiddleware`` has been moved from ``django.middleware.doc`` to
- ``django.contrib.admindocs.middleware`` because it is an implementation
- detail of admindocs, proven not to be reusable in general.
- * :class:`~django.db.models.GenericIPAddressField` will now only allow
- ``blank`` values if ``null`` values are also allowed. Creating a
- ``GenericIPAddressField`` where ``blank`` is allowed but ``null`` is not
- will trigger a model validation error because ``blank`` values are always
- stored as ``null``. Previously, storing a ``blank`` value in a field which
- did not allow ``null`` would cause a database exception at runtime.
- * If a :class:`~django.core.urlresolvers.NoReverseMatch` exception is raised
- from a method when rendering a template, it is not silenced. For example,
- ``{{ obj.view_href }}`` will cause template rendering to fail if
- ``view_href()`` raises ``NoReverseMatch``. There is no change to the
- :ttag:`{% url %}<url>` tag, it causes template rendering to fail like always
- when ``NoReverseMatch`` is raised.
- * :meth:`django.test.Client.logout` now calls
- :meth:`django.contrib.auth.logout` which will send the
- :func:`~django.contrib.auth.signals.user_logged_out` signal.
- * :ref:`Authentication views <built-in-auth-views>` are now reversed by name,
- not their locations in ``django.contrib.auth.views``. If you are using the
- views without a ``name``, you should update your ``urlpatterns`` to use
- :meth:`~django.conf.urls.url` with the ``name`` parameter. For example::
- (r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete')
- becomes::
- url(r'^reset/done/$', 'django.contrib.auth.views.password_reset_complete', name='password_reset_complete')
- * :class:`~django.views.generic.base.RedirectView` now has a `pattern_name`
- attribute which allows it to choose the target by reversing the URL.
- * In Django 1.4 and 1.5, a blank string was unintentionally not considered to
- be a valid password. This meant
- :meth:`~django.contrib.auth.models.User.set_password()` would save a blank
- password as an unusable password like
- :meth:`~django.contrib.auth.models.User.set_unusable_password()` does, and
- thus :meth:`~django.contrib.auth.models.User.check_password()` always
- returned ``False`` for blank passwords. This has been corrected in this
- release: blank passwords are now valid.
- * The admin :attr:`~django.contrib.admin.ModelAdmin.changelist_view` previously
- accepted a ``pop`` GET parameter to signify it was to be displayed in a popup.
- This parameter has been renamed to ``_popup`` to be consistent with the rest
- of the admin views. You should update your custom templates if they use the
- previous parameter name.
- * :meth:`~django.core.validators.validate_email` now accepts email addresses
- with ``localhost`` as the domain.
- * The :djadminopt:`--keep-pot` option was added to :djadmin:`makemessages`
- to prevent django from deleting the temporary .pot file it generates before
- creating the .po file.
- * The undocumented ``django.core.servers.basehttp.WSGIServerException`` has
- been removed. Use ``socket.error`` provided by the standard library instead.
- This change was also released in Django 1.5.5.
- * The signature of :meth:`django.views.generic.base.RedirectView.get_redirect_url`
- has changed and now accepts positional arguments as well (``*args, **kwargs``).
- Any unnamed captured group will now be passed to ``get_redirect_url()``
- which may result in a ``TypeError`` if you don't update the signature of your
- custom method.
- .. _deprecated-features-1.6:
- Features deprecated in 1.6
- ==========================
- Transaction management APIs
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Transaction management was completely overhauled in Django 1.6, and the
- current APIs are deprecated:
- - ``django.middleware.transaction.TransactionMiddleware``
- - ``django.db.transaction.autocommit``
- - ``django.db.transaction.commit_on_success``
- - ``django.db.transaction.commit_manually``
- - the ``TRANSACTIONS_MANAGED`` setting
- ``django.contrib.comments``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Django's comment framework has been deprecated and is no longer supported. It
- will be available in Django 1.6 and 1.7, and removed in Django 1.8. Most users
- will be better served with a custom solution, or a hosted product like Disqus__.
- The code formerly known as ``django.contrib.comments`` is `still available
- in an external repository`__.
- __ https://disqus.com/
- __ https://github.com/django/django-contrib-comments
- Support for PostgreSQL versions older than 8.4
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The end of upstream support periods was reached in December 2011 for
- PostgreSQL 8.2 and in February 2013 for 8.3. As a consequence, Django 1.6 sets
- 8.4 as the minimum PostgreSQL version it officially supports.
- You're strongly encouraged to use the most recent version of PostgreSQL
- available, because of performance improvements and to take advantage of the
- native streaming replication available in PostgreSQL 9.x.
- Changes to :ttag:`cycle` and :ttag:`firstof`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The template system generally escapes all variables to avoid XSS attacks.
- However, due to an accident of history, the :ttag:`cycle` and :ttag:`firstof`
- tags render their arguments as-is.
- Django 1.6 starts a process to correct this inconsistency. The ``future``
- template library provides alternate implementations of :ttag:`cycle` and
- :ttag:`firstof` that autoescape their inputs. If you're using these tags,
- you're encouraged to include the following line at the top of your templates to
- enable the new behavior::
- {% load cycle from future %}
- or::
- {% load firstof from future %}
- The tags implementing the old behavior have been deprecated, and in Django
- 1.8, the old behavior will be replaced with the new behavior. To ensure
- compatibility with future versions of Django, existing templates should be
- modified to use the ``future`` versions.
- If necessary, you can temporarily disable auto-escaping with
- :func:`~django.utils.safestring.mark_safe` or :ttag:`{% autoescape off %}
- <autoescape>`.
- ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``CacheMiddleware`` and ``UpdateCacheMiddleware`` used to provide a way to
- cache requests only if they weren't made by a logged-in user. This mechanism
- was largely ineffective because the middleware correctly takes into account the
- ``Vary: Cookie`` HTTP header, and this header is being set on a variety of
- occasions, such as:
- * accessing the session, or
- * using CSRF protection, which is turned on by default, or
- * using a client-side library which sets cookies, like `Google Analytics`__.
- This makes the cache effectively work on a per-session basis regardless of the
- ``CACHE_MIDDLEWARE_ANONYMOUS_ONLY`` setting.
- __ http://www.google.com/analytics/
- ``SEND_BROKEN_LINK_EMAILS`` setting
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- :class:`~django.middleware.common.CommonMiddleware` used to provide basic
- reporting of broken links by email when ``SEND_BROKEN_LINK_EMAILS`` is set to
- ``True``.
- Because of intractable ordering problems between
- :class:`~django.middleware.common.CommonMiddleware` and
- :class:`~django.middleware.locale.LocaleMiddleware`, this feature was split
- out into a new middleware:
- :class:`~django.middleware.common.BrokenLinkEmailsMiddleware`.
- If you're relying on this feature, you should add
- ``'django.middleware.common.BrokenLinkEmailsMiddleware'`` to your
- :setting:`MIDDLEWARE_CLASSES` setting and remove ``SEND_BROKEN_LINK_EMAILS``
- from your settings.
- ``_has_changed`` method on widgets
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- If you defined your own form widgets and defined the ``_has_changed`` method
- on a widget, you should now define this method on the form field itself.
- ``module_name`` model _meta attribute
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``Model._meta.module_name`` was renamed to ``model_name``. Despite being a
- private API, it will go through a regular deprecation path.
- ``get_(add|change|delete)_permission`` model _meta methods
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- ``Model._meta.get_(add|change|delete)_permission`` methods were deprecated.
- Even if they were not part of the public API they'll also go through
- a regular deprecation path. You can replace them with
- ``django.contrib.auth.get_permission_codename('action', Model._meta)`` where
- ``'action'`` is ``'add'``, ``'change'``, or ``'delete'``.
- ``get_query_set`` and similar methods renamed to ``get_queryset``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Methods that return a ``QuerySet`` such as ``Manager.get_query_set`` or
- ``ModelAdmin.queryset`` have been renamed to ``get_queryset``.
- If you are writing a library that implements, for example, a
- ``Manager.get_query_set`` method, and you need to support old Django versions,
- you should rename the method and conditionally add an alias with the old name::
- class CustomManager(models.Manager):
- def get_queryset(self):
- pass # ...
- if django.VERSION < (1, 6):
- get_query_set = get_queryset
- # For Django >= 1.6, models.Manager provides a get_query_set fallback
- # that emits a warning when used.
- If you are writing a library that needs to call the ``get_queryset`` method and
- must support old Django versions, you should write::
- get_queryset = (some_manager.get_query_set
- if hasattr(some_manager, 'get_query_set')
- else some_manager.get_queryset)
- return get_queryset() # etc
- In the general case of a custom manager that both implements its own
- ``get_queryset`` method and calls that method, and needs to work with older Django
- versions, and libraries that have not been updated yet, it is useful to define
- a ``get_queryset_compat`` method as below and use it internally to your manager::
- class YourCustomManager(models.Manager):
- def get_queryset(self):
- return YourCustomQuerySet() # for example
- get_query_set = get_queryset
- def active(self): # for example
- return self.get_queryset_compat().filter(active=True)
- def get_queryset_compat(self):
- get_queryset = (self.get_query_set
- if hasattr(self, 'get_query_set')
- else self.get_queryset)
- return get_queryset()
- This helps to minimize the changes that are needed, but also works correctly in
- the case of subclasses (such as ``RelatedManagers`` from Django 1.5) which might
- override either ``get_query_set`` or ``get_queryset``.
- ``shortcut`` view and URLconf
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The ``shortcut`` view was moved from ``django.views.defaults`` to
- ``django.contrib.contenttypes.views`` shortly after the 1.0 release, but the
- old location was never deprecated. This oversight was corrected in Django 1.6
- and you should now use the new location.
- The URLconf ``django.conf.urls.shortcut`` was also deprecated. If you're
- including it in an URLconf, simply replace::
- (r'^prefix/', include('django.conf.urls.shortcut')),
- with::
- (r'^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$', 'django.contrib.contenttypes.views.shortcut'),
- ``ModelForm`` without ``fields`` or ``exclude``
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Previously, if you wanted a :class:`~django.forms.ModelForm` to use all fields on
- the model, you could simply omit the ``Meta.fields`` attribute, and all fields
- would be used.
- This can lead to security problems where fields are added to the model and,
- unintentionally, automatically become editable by end users. In some cases,
- particular with boolean fields, it is possible for this problem to be completely
- invisible. This is a form of `Mass assignment vulnerability
- <http://en.wikipedia.org/wiki/Mass_assignment_vulnerability>`_.
- For this reason, this behavior is deprecated, and using the ``Meta.exclude``
- option is strongly discouraged. Instead, all fields that are intended for
- inclusion in the form should be listed explicitly in the ``fields`` attribute.
- If this security concern really does not apply in your case, there is a shortcut
- to explicitly indicate that all fields should be used - use the special value
- ``"__all__"`` for the fields attribute::
- class MyModelForm(ModelForm):
- class Meta:
- fields = "__all__"
- model = MyModel
- If you have custom ``ModelForms`` that only need to be used in the admin, there
- is another option. The admin has its own methods for defining fields
- (``fieldsets`` etc.), and so adding a list of fields to the ``ModelForm`` is
- redundant. Instead, simply omit the ``Meta`` inner class of the ``ModelForm``,
- or omit the ``Meta.model`` attribute. Since the ``ModelAdmin`` subclass knows
- which model it is for, it can add the necessary attributes to derive a
- functioning ``ModelForm``. This behavior also works for earlier Django
- versions.
- ``UpdateView`` and ``CreateView`` without explicit fields
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The generic views :class:`~django.views.generic.edit.CreateView` and
- :class:`~django.views.generic.edit.UpdateView`, and anything else derived from
- :class:`~django.views.generic.edit.ModelFormMixin`, are vulnerable to the
- security problem described in the section above, because they can automatically
- create a ``ModelForm`` that uses all fields for a model.
- For this reason, if you use these views for editing models, you must also supply
- the ``fields`` attribute (new in Django 1.6), which is a list of model fields
- and works in the same way as the :class:`~django.forms.ModelForm`
- ``Meta.fields`` attribute. Alternatively, you can set the ``form_class``
- attribute to a ``ModelForm`` that explicitly defines the fields to be used.
- Defining an ``UpdateView`` or ``CreateView`` subclass to be used with a model
- but without an explicit list of fields is deprecated.
- .. _m2m-help_text-deprecation:
- Munging of help text of model form fields for ``ManyToManyField`` fields
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- All special handling of the ``help_text`` attribute of ``ManyToManyField`` model
- fields performed by standard model or model form fields as described in
- :ref:`m2m-help_text` above is deprecated and will be removed in Django 1.8.
- Help text of these fields will need to be handled either by applications, custom
- form fields or widgets, just like happens with the rest of the model field
- types.
|