============================================= 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` 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 ` 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. * The new :attr:`InlineModelAdmin.classes ` attribute allows specifying classes on inline fieldsets. Inlines with a ``collapse`` class will be initially collapsed and their header will have a small "show" link. * If a user doesn't have the add permission, the ``object-tools`` block on a model's changelist will now be rendered (without the add button, of course). This makes it easier to add custom tools in this case. * The :class:`~django.contrib.admin.models.LogEntry` model now stores change messages in a JSON structure so that the message can be dynamically translated using the current active language. A new ``LogEntry.get_change_message()`` method is now the preferred way of retrieving the change message. :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. * Added the optional ``backend`` argument to :func:`~django.contrib.auth.login` to allow using it without credentials. :mod:`django.contrib.contenttypes` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ * ... :mod:`django.contrib.gis` ^^^^^^^^^^^^^^^^^^^^^^^^^^ * :ref:`Distance lookups ` now accept expressions as the distance value parameter. * The new :attr:`GEOSGeometry.unary_union ` property computes the union of all the elements of this geometry. * Added the :meth:`GEOSGeometry.covers() ` binary predicate. * Added the :meth:`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. * Added support for instantiating empty GEOS geometries. * The new :attr:`~django.contrib.gis.geos.WKTWriter.trim` and :attr:`~django.contrib.gis.geos.WKTWriter.precision` properties of :class:`~django.contrib.gis.geos.WKTWriter` allow controlling output of the fractional part of the coordinates in WKT. * Added the :attr:`LineString.closed ` and :attr:`MultiLineString.closed ` properties. :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 `. :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. * :djadmin:`makemigrations` now displays the path to the migration files that it generates. * The :djadmin:`shell` ``--interface`` option now accepts ``python`` to force use of the "plain" Python interpreter. * The new :djadminopt:`shell --command <--command>` option lets you run a command as Django and exit, instead of opening the interactive shell. 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() ` 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. * Added :class:`~django.db.models.BigAutoField` which acts much like an :class:`~django.db.models.AutoField` except that it is guaranteed to fit numbers from ``1`` to ``9223372036854775807``. * :meth:`QuerySet.in_bulk() ` may be called without any arguments to return all objects in the queryset. 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 ` ``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) Dropped support for PostgreSQL 9.1 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Upstream support for PostgreSQL 9.1 ends in September 2016. As a consequence, Django 1.10 sets PostgreSQL 9.2 as the minimum version it officially supports. Miscellaneous ~~~~~~~~~~~~~ * The ``repr()`` of a ``QuerySet`` is wrapped in ```` 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'). * The ``LOGOUT_URL`` setting is removed as Django hasn't made use of it since pre-1.0. If you use it in your project, you can add it to your project's settings. The default value was ``'/accounts/logout/'``. * The ``add_postgis_srs()`` backwards compatibility alias for ``django.contrib.gis.utils.add_srs_entry()`` is removed. * Objects with a ``close()`` method such as files and generators passed to :class:`~django.http.HttpResponse` are now closed immediately instead of when the WSGI server calls ``close()`` on the response. * A redundant ``transaction.atomic()`` call in ``QuerySet.update_or_create()`` is removed. This may affect query counts tested by ``TransactionTestCase.assertNumQueries()``. * Support for ``skip_validation`` in ``BaseCommand.execute(**options)`` is removed. Use ``skip_checks`` (added in Django 1.7) instead. * :djadmin:`loaddata` now raises a ``CommandError`` instead of showing a warning when the specified fixture file is not found. * Instead of directly accessing the ``LogEntry.change_message`` attribute, it's now better to call the ``LogEntry.get_change_message()`` method which will provide the message in the current language. .. _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. * ``django.utils.functional.allow_lazy()`` is deprecated in favor of the new :func:`~django.utils.functional.keep_lazy` function which can be used with a more natural decorator syntax. * The ``shell --plain`` option is deprecated in favor of ``-i python`` or ``--interface python``. * Importing from the ``django.core.urlresolvers`` module is deprecated in favor of its new location, :mod:`django.urls`. .. _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 ` 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.urls.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 ` 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 ``%()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``.