=============================================
Django 1.10 release notes - UNDER DEVELOPMENT
=============================================

Welcome to Django 1.10!

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.9 or older versions. We've :ref:`dropped some features<removed-features-1.10>`
that have reached the end of their deprecation cycle, and we've `begun the
deprecation process for some features`_.

.. _`new features`: `What's new in Django 1.10`_
.. _`backwards incompatible changes`: `Backwards incompatible changes in 1.10`_
.. _`dropped some features`: `Features removed in 1.10`_
.. _`begun the deprecation process for some features`: `Features deprecated in 1.10`_

Python compatibility
====================

Like Django 1.9, Django 1.10 requires Python 2.7, 3.4, or 3.5. We **highly
recommend** and only officially support the latest release of each series.

What's new in Django 1.10
=========================

...

Minor features
~~~~~~~~~~~~~~

:mod:`django.contrib.admin`
^^^^^^^^^^^^^^^^^^^^^^^^^^^

* For sites running on a subpath, the default :attr:`URL for the "View site"
  link <django.contrib.admin.AdminSite.site_url>` at the top of each admin page
  will now point to ``request.META['SCRIPT_NAME']`` if set, instead of ``/``.

* The success message that appears after adding or editing an object now
  contains a link to the object's change form.

* All inline JavaScript is removed so you can enable the
  ``Content-Security-Policy`` HTTP header if you wish.

:mod:`django.contrib.admindocs`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.auth`
^^^^^^^^^^^^^^^^^^^^^^^^^^

* The default iteration count for the PBKDF2 password hasher has been increased
  by 25%. This backwards compatible change will not affect users who have
  subclassed ``django.contrib.auth.hashers.PBKDF2PasswordHasher`` to change the
  default value.

* The :func:`~django.contrib.auth.views.logout` view sends "no-cache" headers
  to prevent an issue where Safari caches redirects and prevents a user from
  being able to log out.

:mod:`django.contrib.contenttypes`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.gis`
^^^^^^^^^^^^^^^^^^^^^^^^^^

* :ref:`Distance lookups <distance-lookups>` now accept expressions as the
  distance value parameter.

* The new :attr:`GEOSGeometry.unary_union
  <django.contrib.gis.geos.GEOSGeometry.unary_union>` property computes the
  union of all the elements of this geometry.

* Added the :meth:`GEOSGeometry.covers()
  <django.contrib.gis.geos.GEOSGeometry.covers>` binary predicate.

* Added the :meth:`GDALBand.statistics()
  <django.contrib.gis.gdal.GDALBand.statistics>` method and
  :attr:`~django.contrib.gis.gdal.GDALBand.mean`
  and :attr:`~django.contrib.gis.gdal.GDALBand.std` attributes.

* Added support for the :class:`~django.contrib.gis.db.models.MakeLine`
  aggregate and :class:`~django.contrib.gis.db.models.functions.GeoHash`
  function on SpatiaLite.

* Added support for the
  :class:`~django.contrib.gis.db.models.functions.Difference`,
  :class:`~django.contrib.gis.db.models.functions.Intersection`, and
  :class:`~django.contrib.gis.db.models.functions.SymDifference`
  functions on MySQL.

:mod:`django.contrib.messages`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.postgres`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.redirects`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.sessions`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* The :djadmin:`clearsessions` management command now removes file-based
  sessions.

:mod:`django.contrib.sitemaps`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

:mod:`django.contrib.sites`
^^^^^^^^^^^^^^^^^^^^^^^^^^^

* The :class:`~django.contrib.sites.models.Site` model now supports
  :ref:`natural keys <topics-serialization-natural-keys>`.

:mod:`django.contrib.staticfiles`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* The :ttag:`static` template tag now uses ``django.contrib.staticfiles``
  if it's in ``INSTALLED_APPS``. This is especially useful for third-party apps
  which can now always use ``{% load static %}`` (instead of
  ``{% load staticfiles %}`` or ``{% load static from staticfiles %}``) and
  not worry about whether or not the ``staticfiles`` app is installed.

:mod:`django.contrib.syndication`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

* ...

Cache
^^^^^

* The file-based cache backend now uses the highest pickling protocol.

CSRF
^^^^

* The default :setting:`CSRF_FAILURE_VIEW`, ``views.csrf.csrf_failure()`` now
  accepts an optional ``template_name`` parameter, defaulting to
  ``'403_csrf.html'``, to control the template used to render the page.

Database backends
^^^^^^^^^^^^^^^^^

* ...

Email
^^^^^

* ...

File Storage
^^^^^^^^^^^^

* ...

File Uploads
^^^^^^^^^^^^

* ...

Forms
^^^^^

* Form and widget ``Media`` is now served using
  :mod:`django.contrib.staticfiles` if installed.

Generic Views
^^^^^^^^^^^^^

* ...

Internationalization
^^^^^^^^^^^^^^^^^^^^

* ...

Management Commands
^^^^^^^^^^^^^^^^^^^

* The new :djadminopt:`--fail-level` option of the :djadmin:`check` command
  allows specifying the message level that will cause the command to exit with
  a non-zero status.

* The new :djadminopt:`makemigrations --check <--check>` option makes the
  command exit with a non-zero status when model changes without migrations are
  detected.

Migrations
^^^^^^^^^^

* Added support for serialization of ``enum.Enum`` objects.

Models
^^^^^^

* Reverse foreign keys from proxy models are now propagated to their
  concrete class. The reverse relation attached by a
  :class:`~django.db.models.ForeignKey` pointing to a proxy model is now
  accessible as a descriptor on the proxied model class and may be referenced in
  queryset filtering.

* The new :meth:`Field.rel_db_type() <django.db.models.Field.rel_db_type>`
  method returns the database column data type for fields such as ``ForeignKey``
  and ``OneToOneField`` that point to another field.

* The :attr:`~django.db.models.Func.arity` class attribute is added to
  :class:`~django.db.models.Func`. This attribute can be used to set the number
  of arguments the function accepts.

Requests and Responses
^^^^^^^^^^^^^^^^^^^^^^

* Added ``request.user`` to the debug view.

* Added :class:`~django.http.HttpResponse` methods
  :meth:`~django.http.HttpResponse.readable()` and
  :meth:`~django.http.HttpResponse.seekable()` to make an instance a
  stream-like object and allow wrapping it with :py:class:`io.TextIOWrapper`.

Serialization
^^^^^^^^^^^^^

* The ``django.core.serializers.json.DjangoJSONEncoder`` now knows how to
  serialize lazy strings, typically used for translatable content.

Signals
^^^^^^^

* ...

Templates
^^^^^^^^^

* Added the ``autoescape`` option to the
  :class:`~django.template.backends.django.DjangoTemplates` backend and the
  :class:`~django.template.Engine` class.

Tests
^^^^^

* ...

URLs
^^^^

* An addition in :func:`django.setup()` allows URL resolving that happens
  outside of the request/response cycle (e.g. in management commands and
  standalone scripts) to take :setting:`FORCE_SCRIPT_NAME` into account when it
  is set.

Validators
^^^^^^^^^^

* :class:`~django.core.validators.URLValidator` now limits the length of
  domain name labels to 63 characters and the total length of domain
  names to 253 characters per :rfc:`1034`.

Backwards incompatible changes in 1.10
======================================

.. warning::

    In addition to the changes outlined in this section, be sure to review the
    :ref:`removed-features-1.10` for the features that have reached the end of
    their deprecation cycle and therefore 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.

Database backend API
~~~~~~~~~~~~~~~~~~~~

* ...

``select_related()`` prohibits non-relational fields for nested relations
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Django 1.8 added validation for non-relational fields in ``select_related()``::

    >>> Book.objects.select_related('title')
    Traceback (most recent call last):
    ...
    FieldError: Non-relational field given in select_related: 'title'

But it didn't prohibit nested non-relation fields as it does now::

    >>> Book.objects.select_related('author__name')
    Traceback (most recent call last):
    ...
    FieldError: Non-relational field given in select_related: 'name'

``_meta.get_fields()`` returns consistent reverse fields for proxy models
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Before Django 1.10, the :meth:`~django.db.models.options.Options.get_fields`
method returned different reverse fields when called on a proxy model compared
to its proxied concrete class. This inconsistency was fixed by returning the
full set of fields pointing to a concrete class or one of its proxies in both
cases.

:attr:`AbstractUser.username <django.contrib.auth.models.User.username>` ``max_length`` increased to 254
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

A migration for :attr:`django.contrib.auth.models.User.username` is included.
If you have a custom user model inheriting from ``AbstractUser``, you'll need
to generate and apply a database migration for your user model.

If you want to preserve the 30 character limit for usernames, use a custom form
when creating a user or changing usernames::

    from django.contrib.auth.forms import UserCreationForm

    class MyUserCreationForm(UserCreationForm):
        username = forms.CharField(
            max_length=30,
            help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.',
        )

If you wish to keep this restriction in the admin, set ``UserAdmin.add_form``
to use this form::

    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    from django.contrib.auth.models import User

    class UserAdmin(BaseUserAdmin):
        add_form = MyUserCreationForm

    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)

Miscellaneous
~~~~~~~~~~~~~

* The ``repr()`` of a ``QuerySet`` is wrapped in ``<QuerySet >`` to
  disambiguate it from a plain list when debugging.

* Support for SpatiaLite < 3.0 and GEOS < 3.3 is dropped.

* ``utils.version.get_version()`` returns :pep:`440` compliant release
  candidate versions (e.g. '1.10rc1' instead of '1.10c1').

.. _deprecated-features-1.10:

Features deprecated in 1.10
===========================

Direct assignment to a reverse foreign key or many-to-many relation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Instead of assigning related objects using direct assignment::

    >>> new_list = [obj1, obj2, obj3]
    >>> e.related_set = new_list

Use the :meth:`~django.db.models.fields.related.RelatedManager.set` method
added in Django 1.9::

        >>> e.related_set.set([obj1, obj2, obj3])

This prevents confusion about an assignment resulting in an implicit save.

:mod:`django.contrib.gis`
~~~~~~~~~~~~~~~~~~~~~~~~~

* The ``get_srid()`` and ``set_srid()`` methods of
  :class:`~django.contrib.gis.geos.GEOSGeometry` are deprecated in favor
  of the :attr:`~django.contrib.gis.geos.GEOSGeometry.srid` property.

* The ``get_x()``, ``set_x()``, ``get_y()``, ``set_y()``, ``get_z()``, and
  ``set_z()`` methods of :class:`~django.contrib.gis.geos.Point` are deprecated
  in favor of the ``x``, ``y``, and ``z`` properties.

* The ``get_coords()`` and ``set_coords()`` methods of
  :class:`~django.contrib.gis.geos.Point` are deprecated in favor of the
  ``tuple`` property.

* The ``cascaded_union`` property of
  :class:`~django.contrib.gis.geos.MultiPolygon` is deprecated in favor of the
  :attr:`~django.contrib.gis.geos.GEOSGeometry.unary_union` property.

Miscellaneous
~~~~~~~~~~~~~

* The ``makemigrations --exit`` option is deprecated in favor of the
  :djadminopt:`--check` option.

.. _removed-features-1.10:

Features removed in 1.10
========================

These features have reached the end of their deprecation cycle and so have been
removed in Django 1.10 (please see the :ref:`deprecation timeline
<deprecation-removed-in-1.10>` for more details):

* Support for calling a ``SQLCompiler`` directly as an alias for calling its
  ``quote_name_unless_alias`` method is removed.

* The ``cycle`` and ``firstof`` template tags are removed from the ``future``
  template tag library.

* ``django.conf.urls.patterns()`` is removed.

* Support for the ``prefix`` argument to
  ``django.conf.urls.i18n.i18n_patterns()`` is removed.

* ``SimpleTestCase.urls`` is removed.

* Using an incorrect count of unpacked values in the ``for`` template tag
  raises an exception rather than failing silently.

* The ability to :func:`~django.core.urlresolvers.reverse` URLs using a dotted
  Python path is removed.

* Support for ``optparse`` is dropped for custom management commands.

* The class ``django.core.management.NoArgsCommand`` is removed.

* ``django.core.context_processors`` module is removed.

* ``django.db.models.sql.aggregates`` module is removed.

* ``django.contrib.gis.db.models.sql.aggregates`` module is removed.

* The following methods and properties of ``django.db.sql.query.Query`` are
  removed:

  * Properties: ``aggregates`` and ``aggregate_select``
  * Methods: ``add_aggregate``, ``set_aggregate_mask``, and
    ``append_aggregate_mask``.

* ``django.template.resolve_variable`` is removed.

* The following private APIs are removed from
  :class:`django.db.models.options.Options` (``Model._meta``):

  * ``get_field_by_name()``
  * ``get_all_field_names()``
  * ``get_fields_with_model()``
  * ``get_concrete_fields_with_model()``
  * ``get_m2m_with_model()``
  * ``get_all_related_objects()``
  * ``get_all_related_objects_with_model()``
  * ``get_all_related_many_to_many_objects()``
  * ``get_all_related_m2m_objects_with_model()``

* The ``error_message`` argument of ``django.forms.RegexField`` is removed.

* The ``unordered_list`` filter no longer supports old style lists.

* Support for string ``view`` arguments to ``url()`` is removed.

* The backward compatible shim  to rename ``django.forms.Form._has_changed()``
  to ``has_changed()`` is removed.

* The ``removetags`` template filter is removed.

* The ``remove_tags()`` and ``strip_entities()`` functions in
  ``django.utils.html`` is removed.

* The ``is_admin_site`` argument to
  ``django.contrib.auth.views.password_reset()`` is removed.

* ``django.db.models.field.subclassing.SubfieldBase`` is removed.

* ``django.utils.checksums`` is removed.

* The ``original_content_type_id`` attribute on
  ``django.contrib.admin.helpers.InlineAdminForm`` is removed.

* The backwards compatibility shim to allow ``FormMixin.get_form()`` to be
  defined with no default value for its ``form_class`` argument is removed.

* The following settings are removed:

  * ``ALLOWED_INCLUDE_ROOTS``
  * ``TEMPLATE_CONTEXT_PROCESSORS``
  * ``TEMPLATE_DEBUG``
  * ``TEMPLATE_DIRS``
  * ``TEMPLATE_LOADERS``
  * ``TEMPLATE_STRING_IF_INVALID``

* The backwards compatibility alias ``django.template.loader.BaseLoader`` is
  removed.

* Django template objects returned by
  :func:`~django.template.loader.get_template` and
  :func:`~django.template.loader.select_template` no longer accept a
  :class:`~django.template.Context` in their
  :meth:`~django.template.backends.base.Template.render()` method.

* :doc:`Template response APIs </ref/template-response>` enforce the use of
  :class:`dict` and backend-dependent template objects instead of
  :class:`~django.template.Context` and :class:`~django.template.Template`
  respectively.

* The ``current_app`` parameter for the following function and classes is
  removed:

  * ``django.shortcuts.render()``
  * ``django.template.Context()``
  * ``django.template.RequestContext()``
  * ``django.template.response.TemplateResponse()``

* The ``dictionary`` and ``context_instance`` parameters for the following
  functions are removed:

  * ``django.shortcuts.render()``
  * ``django.shortcuts.render_to_response()``
  * ``django.template.loader.render_to_string()``

* The ``dirs`` parameter for the following functions is removed:

  * ``django.template.loader.get_template()``
  * ``django.template.loader.select_template()``
  * ``django.shortcuts.render()``
  * ``django.shortcuts.render_to_response()``

* Session verification is enabled regardless of whether or not
  ``'django.contrib.auth.middleware.SessionAuthenticationMiddleware'`` is in
  ``MIDDLEWARE_CLASSES``. ``SessionAuthenticationMiddleware`` no longer has
  any purpose and can be removed from ``MIDDLEWARE_CLASSES``. It's kept as
  a stub until Django 2.0 as a courtesy for users who don't read this note.

* Private attribute ``django.db.models.Field.related`` is removed.

* The ``--list`` option of the ``migrate`` management command is removed.

* The ``ssi`` template tag is removed.

* Support for the ``=`` comparison operator in the ``if`` template tag is
  removed.

* The backwards compatibility shims to allow ``Storage.get_available_name()``
  and ``Storage.save()`` to be defined without a ``max_length`` argument are
  removed.

* Support for the legacy ``%(<foo>)s`` syntax in ``ModelFormMixin.success_url``
  is removed.

* ``GeoQuerySet`` aggregate methods ``collect()``, ``extent()``, ``extent3d()``,
  ``make_line()``, and ``unionagg()`` are removed.

* The ability to specify ``ContentType.name`` when creating a content type
  instance is removed.

* Support for the old signature of ``allow_migrate`` is removed.

* Support for the syntax of ``{% cycle %}`` that uses comma-separated arguments
  is removed.

* The warning that :class:`~django.core.signing.Signer` issued when given an
  invalid separator is now a ``ValueError``.
