======================== Django 1.8 release notes ======================== *April 1, 2015* Welcome to Django 1.8! 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.7 or older versions. We've also `begun the deprecation process for some features`_, and some features have reached the end of their deprecation process and `have been removed`_. Django 1.8 has been designated as Django's second :term:`long-term support release`. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 1.4, will end 6 months from the release date of Django 1.8. .. _`new features`: `What's new in Django 1.8`_ .. _`backwards incompatible changes`: `Backwards incompatible changes in 1.8`_ .. _`begun the deprecation process for some features`: `Features deprecated in 1.8`_ .. _`have been removed`: `Features removed in 1.8`_ Python compatibility ==================== Django 1.8 requires Python 2.7, 3.2, 3.3, 3.4, or 3.5. We **highly recommend** and only officially support the latest release of each series. Django 1.8 is the first release to support Python 3.5. Due to the end of upstream support for Python 3.2 in February 2016, we won't test Django 1.8.x on Python 3.2 after the end of 2016. What's new in Django 1.8 ======================== ``Model._meta`` API ~~~~~~~~~~~~~~~~~~~ Django now has a formalized API for :doc:`Model._meta `, providing an officially supported way to :ref:`retrieve fields ` and filter fields based on their :ref:`attributes `. The ``Model._meta`` object has been part of Django since the days of pre-0.96 "Magic Removal" -- it just wasn't an official, stable API. In recognition of this, we've endeavored to maintain backwards-compatibility with the old API endpoint where possible. However, API endpoints that aren't part of the new official API have been deprecated and will eventually be removed. A :ref:`guide to migrating from the old API to the new API ` has been provided. Multiple template engines ~~~~~~~~~~~~~~~~~~~~~~~~~ Django 1.8 defines a stable API for integrating template backends. It includes built-in support for the Django template language and for :class:`~django.template.backends.jinja2.Jinja2`. It supports rendering templates with multiple engines within the same project. Learn more about the new features in the :doc:`topic guide ` and check the :doc:`upgrade instructions ` for details. Security enhancements ~~~~~~~~~~~~~~~~~~~~~ Several features of the django-secure_ third-party library have been integrated into Django. :class:`django.middleware.security.SecurityMiddleware` provides several security enhancements to the request/response cycle. The new :option:`check --deploy` option allows you to check your production settings file for ways to increase the security of your site. .. _django-secure: https://pypi.python.org/pypi/django-secure New PostgreSQL specific functionality ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Django now has a module with extensions for PostgreSQL specific features, such as :class:`~django.contrib.postgres.fields.ArrayField`, :class:`~django.contrib.postgres.fields.HStoreField`, :ref:`range-fields`, and :lookup:`unaccent` lookup. A full breakdown of the features is available :doc:`in the documentation `. New data types ~~~~~~~~~~~~~~ * Django now has a :class:`~django.db.models.UUIDField` for storing universally unique identifiers. It is stored as the native ``uuid`` data type on PostgreSQL and as a fixed length character field on other backends. There is a corresponding :class:`form field `. * Django now has a :class:`~django.db.models.DurationField` for storing periods of time - modeled in Python by :class:`~python:datetime.timedelta`. It is stored in the native ``interval`` data type on PostgreSQL, as a ``INTERVAL DAY(9) TO SECOND(6)`` on Oracle, and as a ``bigint`` of microseconds on other backends. Date and time related arithmetic has also been improved on all backends. There is a corresponding :class:`form field `. Query Expressions, Conditional Expressions, and Database Functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ :doc:`Query Expressions ` allow you to create, customize, and compose complex SQL expressions. This has enabled annotate to accept expressions other than aggregates. Aggregates are now able to reference multiple fields, as well as perform arithmetic, similar to ``F()`` objects. :meth:`~django.db.models.query.QuerySet.order_by` has also gained the ability to accept expressions. :doc:`Conditional Expressions ` allow you to use :keyword:`if` ... :keyword:`elif` ... :keyword:`else` logic within queries. A collection of :doc:`database functions ` is also included with functionality such as :class:`~django.db.models.functions.Coalesce`, :class:`~django.db.models.functions.Concat`, and :class:`~django.db.models.functions.Substr`. ``TestCase`` data setup ~~~~~~~~~~~~~~~~~~~~~~~ :class:`~django.test.TestCase` has been refactored to allow for data initialization at the class level using transactions and savepoints. Database backends which do not support transactions, like MySQL with the MyISAM storage engine, will still be able to run these tests but won't benefit from the improvements. Tests are now run within two nested :func:`~django.db.transaction.atomic()` blocks: one for the whole class and one for each test. * The class method :meth:`TestCase.setUpTestData() ` adds the ability to setup test data at the class level. Using this technique can speed up the tests as compared to using ``setUp()``. * Fixture loading within ``TestCase`` is now performed once for the whole ``TestCase``. Minor features ~~~~~~~~~~~~~~ :mod:`django.contrib.admin` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * :class:`~django.contrib.admin.ModelAdmin` now has a :meth:`~django.contrib.admin.ModelAdmin.has_module_permission` method to allow limiting access to the module on the admin index page. * :class:`~django.contrib.admin.InlineModelAdmin` now has an attribute :attr:`~django.contrib.admin.InlineModelAdmin.show_change_link` that supports showing a link to an inline object's change form. * Use the new ``django.contrib.admin.RelatedOnlyFieldListFilter`` in :attr:`ModelAdmin.list_filter ` to limit the ``list_filter`` choices to foreign objects which are attached to those from the ``ModelAdmin``. * The :meth:`ModelAdmin.delete_view() ` displays a summary of objects to be deleted on the deletion confirmation page. * The jQuery library embedded in the admin has been upgraded to version 1.11.2. * You can now specify :attr:`AdminSite.site_url ` in order to display a link to the front-end site. * You can now specify :attr:`ModelAdmin.show_full_result_count ` to control whether or not the full count of objects should be displayed on a filtered admin page. * The ``AdminSite.password_change()`` method now has an ``extra_context`` parameter. * You can now control who may login to the admin site by overriding only :meth:`AdminSite.has_permission() ` and :attr:`AdminSite.login_form `. The ``base.html`` template has a new block ``usertools`` which contains the user-specific header. A new context variable ``has_permission``, which gets its value from :meth:`~django.contrib.admin.AdminSite.has_permission`, indicates whether the user may access the site. * Foreign key dropdowns now have buttons for changing or deleting related objects using a popup. :mod:`django.contrib.admindocs` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * reStructuredText is now parsed in model docstrings. :mod:`django.contrib.auth` ^^^^^^^^^^^^^^^^^^^^^^^^^^ * Authorization backends can now raise :class:`~django.core.exceptions.PermissionDenied` in :meth:`~django.contrib.auth.models.User.has_perm` and :meth:`~django.contrib.auth.models.User.has_module_perms` to short-circuit permission checking. * :class:`~django.contrib.auth.forms.PasswordResetForm` now has a method :meth:`~django.contrib.auth.forms.PasswordResetForm.send_email` that can be overridden to customize the mail to be sent. * The ``max_length`` of :attr:`Permission.name ` has been increased from 50 to 255 characters. Please run the database migration. * :attr:`~django.contrib.auth.models.CustomUser.USERNAME_FIELD` and :attr:`~django.contrib.auth.models.CustomUser.REQUIRED_FIELDS` now supports :class:`~django.db.models.ForeignKey`\s. * The default iteration count for the PBKDF2 password hasher has been increased by 33%. This backwards compatible change will not affect users who have subclassed ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the default value. :mod:`django.contrib.gis` ^^^^^^^^^^^^^^^^^^^^^^^^^^ * A new :doc:`GeoJSON serializer ` is now available. * It is now allowed to include a subquery as a geographic lookup argument, for example ``City.objects.filter(point__within=Country.objects.filter(continent='Africa').values('mpoly'))``. * The Spatialite backend now supports ``Collect`` and ``Extent`` aggregates when the database version is 3.0 or later. * The PostGIS 2 ``CREATE EXTENSION postgis`` and the Spatialite ``SELECT InitSpatialMetaData`` initialization commands are now automatically run by :djadmin:`migrate`. * The GDAL interface now supports retrieving properties of :ref:`raster (image) data file `. * Compatibility shims for ``SpatialRefSys`` and ``GeometryColumns`` changed in Django 1.2 have been removed. * All GDAL-related exceptions are now raised with ``GDALException``. The former ``OGRException`` has been kept for backwards compatibility but should not be used any longer. :mod:`django.contrib.sessions` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * Session cookie is now deleted after :meth:`~django.contrib.sessions.backends.base.SessionBase.flush()` is called. :mod:`django.contrib.sitemaps` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * The new :attr:`Sitemap.i18n ` attribute allows you to generate a sitemap based on the :setting:`LANGUAGES` setting. :mod:`django.contrib.sites` ^^^^^^^^^^^^^^^^^^^^^^^^^^^ * :func:`~django.contrib.sites.shortcuts.get_current_site` will now lookup the current site based on :meth:`request.get_host() ` if the :setting:`SITE_ID` setting is not defined. * The default :class:`~django.contrib.sites.models.Site` created when running ``migrate`` now respects the :setting:`SITE_ID` setting (instead of always using ``pk=1``). Cache ^^^^^ * The ``incr()`` method of the ``django.core.cache.backends.locmem.LocMemCache`` backend is now thread-safe. Cryptography ^^^^^^^^^^^^ * The ``max_age`` parameter of the :meth:`django.core.signing.TimestampSigner.unsign` method now also accepts a :py:class:`datetime.timedelta` object. Database backends ^^^^^^^^^^^^^^^^^ * The MySQL backend no longer strips microseconds from ``datetime`` values as MySQL 5.6.4 and up supports fractional seconds depending on the declaration of the datetime field (when ``DATETIME`` includes fractional precision greater than 0). New datetime database columns created with Django 1.8 and MySQL 5.6.4 and up will support microseconds. See the :ref:`MySQL database notes ` for more details. * The MySQL backend no longer creates explicit indexes for foreign keys when using the InnoDB storage engine, as MySQL already creates them automatically. * The Oracle backend no longer defines the ``connection_persists_old_columns`` feature as ``True``. Instead, Oracle will now include a cache busting clause when getting the description of a table. Email ^^^^^ * :ref:`Email backends ` now support the context manager protocol for opening and closing connections. * The SMTP email backend now supports ``keyfile`` and ``certfile`` authentication with the :setting:`EMAIL_SSL_CERTFILE` and :setting:`EMAIL_SSL_KEYFILE` settings. * The SMTP :class:`~django.core.mail.backends.smtp.EmailBackend` now supports setting the ``timeout`` parameter with the :setting:`EMAIL_TIMEOUT` setting. * :class:`~django.core.mail.EmailMessage` and ``EmailMultiAlternatives`` now support the ``reply_to`` parameter. File Storage ^^^^^^^^^^^^ * :meth:`Storage.get_available_name() ` and :meth:`Storage.save() ` now take a ``max_length`` argument to implement storage-level maximum filename length constraints. Filenames exceeding this argument will get truncated. This prevents a database error when appending a unique suffix to a long filename that already exists on the storage. See the :ref:`deprecation note ` about adding this argument to your custom storage classes. Forms ^^^^^ * Form widgets now render attributes with a value of ``True`` or ``False`` as HTML5 boolean attributes. * The new :meth:`~django.forms.Form.has_error()` method allows checking if a specific error has happened. * If :attr:`~django.forms.Form.required_css_class` is defined on a form, then the ``