2019-12-02 18:53:58 +08:00
|
|
|
========================
|
|
|
|
Django 3.0 release notes
|
|
|
|
========================
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-12-02 16:10:15 +08:00
|
|
|
*December 2, 2019*
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
Welcome to Django 3.0!
|
|
|
|
|
|
|
|
These release notes cover the :ref:`new features <whats-new-3.0>`, as well as
|
|
|
|
some :ref:`backwards incompatible changes <backwards-incompatible-3.0>` you'll
|
|
|
|
want to be aware of when upgrading from Django 2.2 or earlier. We've
|
|
|
|
:ref:`dropped some features<removed-features-3.0>` that have reached the end of
|
|
|
|
their deprecation cycle, and we've :ref:`begun the deprecation process for
|
|
|
|
some features <deprecated-features-3.0>`.
|
|
|
|
|
|
|
|
See the :doc:`/howto/upgrade-version` guide if you're updating an existing
|
|
|
|
project.
|
|
|
|
|
|
|
|
Python compatibility
|
|
|
|
====================
|
|
|
|
|
2020-10-13 14:35:01 +08:00
|
|
|
Django 3.0 supports Python 3.6, 3.7, 3.8, and 3.9 (as of 3.0.11). We **highly
|
|
|
|
recommend** and only officially support the latest release of each series.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
The Django 2.2.x series is the last to support Python 3.5.
|
|
|
|
|
|
|
|
Third-party library support for older version of Django
|
|
|
|
=======================================================
|
|
|
|
|
|
|
|
Following the release of Django 3.0, we suggest that third-party app authors
|
|
|
|
drop support for all versions of Django prior to 2.2. At that time, you should
|
|
|
|
be able to run your package's tests using ``python -Wd`` so that deprecation
|
|
|
|
warnings appear. After making the deprecation warning fixes, your app should be
|
|
|
|
compatible with Django 3.0.
|
|
|
|
|
|
|
|
.. _whats-new-3.0:
|
|
|
|
|
|
|
|
What's new in Django 3.0
|
|
|
|
========================
|
|
|
|
|
2019-05-28 01:59:49 +08:00
|
|
|
MariaDB support
|
|
|
|
---------------
|
|
|
|
|
|
|
|
Django now officially supports `MariaDB <https://mariadb.org/>`_ 10.1 and
|
|
|
|
higher. See :ref:`MariaDB notes <mariadb-notes>` for more details.
|
|
|
|
|
2019-04-12 21:15:18 +08:00
|
|
|
ASGI support
|
|
|
|
------------
|
|
|
|
|
|
|
|
Django 3.0 begins our journey to making Django fully async-capable by providing
|
|
|
|
support for running as an `ASGI <https://asgi.readthedocs.io/>`_ application.
|
|
|
|
|
|
|
|
This is in addition to our existing WSGI support. Django intends to support
|
|
|
|
both for the foreseeable future. Async features will only be available to
|
|
|
|
applications that run under ASGI, however.
|
|
|
|
|
2020-02-20 22:05:47 +08:00
|
|
|
At this stage async support only applies to the outer ASGI application.
|
|
|
|
Internally everything remains synchronous. Asynchronous middleware, views, etc.
|
|
|
|
are not yet supported. You can, however, use ASGI middleware around Django's
|
|
|
|
application, allowing you to combine Django with other ASGI frameworks.
|
|
|
|
|
2019-04-12 21:15:18 +08:00
|
|
|
There is no need to switch your applications over unless you want to start
|
|
|
|
experimenting with asynchronous code, but we have
|
|
|
|
:doc:`documentation on deploying with ASGI </howto/deployment/asgi/index>` if
|
|
|
|
you want to learn more.
|
|
|
|
|
|
|
|
Note that as a side-effect of this change, Django is now aware of asynchronous
|
|
|
|
event loops and will block you calling code marked as "async unsafe" - such as
|
|
|
|
ORM operations - from an asynchronous context. If you were using Django from
|
|
|
|
async code before, this may trigger if you were doing it incorrectly. If you
|
|
|
|
see a ``SynchronousOnlyOperation`` error, then closely examine your code and
|
|
|
|
move any database operations to be in a synchronous child thread.
|
|
|
|
|
2019-07-12 19:08:00 +08:00
|
|
|
Exclusion constraints on PostgreSQL
|
|
|
|
-----------------------------------
|
|
|
|
|
|
|
|
The new :class:`~django.contrib.postgres.constraints.ExclusionConstraint` class
|
|
|
|
enable adding exclusion constraints on PostgreSQL. Constraints are added to
|
|
|
|
models using the
|
|
|
|
:attr:`Meta.constraints <django.db.models.Options.constraints>` option.
|
|
|
|
|
2017-02-27 17:01:52 +08:00
|
|
|
Filter expressions
|
|
|
|
------------------
|
|
|
|
|
2019-09-10 15:58:42 +08:00
|
|
|
Expressions that output :class:`~django.db.models.BooleanField` may now be
|
2017-02-27 17:01:52 +08:00
|
|
|
used directly in ``QuerySet`` filters, without having to first annotate and
|
|
|
|
then filter against the annotation.
|
|
|
|
|
2019-01-01 01:57:35 +08:00
|
|
|
Enumerations for model field choices
|
|
|
|
------------------------------------
|
|
|
|
|
|
|
|
Custom enumeration types ``TextChoices``, ``IntegerChoices``, and ``Choices``
|
|
|
|
are now available as a way to define :attr:`.Field.choices`. ``TextChoices``
|
|
|
|
and ``IntegerChoices`` types are provided for text and integer fields. The
|
|
|
|
``Choices`` class allows defining a compatible enumeration for other concrete
|
|
|
|
data types. These custom enumeration types support human-readable labels that
|
|
|
|
can be translated and accessed via a property on the enumeration or its
|
2019-09-13 21:37:41 +08:00
|
|
|
members. See :ref:`Enumeration types <field-choices-enum-types>` for more
|
2019-01-01 01:57:35 +08:00
|
|
|
details and examples.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Minor features
|
|
|
|
--------------
|
|
|
|
|
|
|
|
:mod:`django.contrib.admin`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-03-25 15:39:11 +08:00
|
|
|
* Added support for the ``admin_order_field`` attribute on properties in
|
2019-03-19 23:51:35 +08:00
|
|
|
:attr:`.ModelAdmin.list_display`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-19 23:13:26 +08:00
|
|
|
* The new :meth:`ModelAdmin.get_inlines()
|
|
|
|
<django.contrib.admin.ModelAdmin.get_inlines>` method allows specifying the
|
|
|
|
inlines based on the request or model instance.
|
|
|
|
|
2019-07-10 18:31:16 +08:00
|
|
|
* Select2 library is upgraded from version 4.0.3 to 4.0.7.
|
|
|
|
|
2019-05-24 21:41:19 +08:00
|
|
|
* jQuery is upgraded from version 3.3.1 to 3.4.1.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
:mod:`django.contrib.auth`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-05-23 20:18:49 +08:00
|
|
|
* The new ``reset_url_token`` attribute in
|
2019-09-10 15:58:42 +08:00
|
|
|
:class:`~django.contrib.auth.views.PasswordResetConfirmView` allows
|
|
|
|
specifying a token parameter displayed as a component of password reset
|
|
|
|
URLs.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-09 00:48:50 +08:00
|
|
|
* Added :class:`~django.contrib.auth.backends.BaseBackend` class to ease
|
|
|
|
customization of authentication backends.
|
|
|
|
|
2019-03-24 07:40:44 +08:00
|
|
|
* Added :meth:`~django.contrib.auth.models.User.get_user_permissions()` method
|
|
|
|
to mirror the existing
|
|
|
|
:meth:`~django.contrib.auth.models.User.get_group_permissions()` method.
|
|
|
|
|
2019-03-10 18:03:42 +08:00
|
|
|
* Added HTML ``autocomplete`` attribute to widgets of username, email, and
|
|
|
|
password fields in :mod:`django.contrib.auth.forms` for better interaction
|
|
|
|
with browser password managers.
|
|
|
|
|
2019-06-22 05:38:27 +08:00
|
|
|
* :djadmin:`createsuperuser` now falls back to environment variables for
|
|
|
|
password and required fields, when a corresponding command line argument
|
|
|
|
isn't provided in non-interactive mode.
|
|
|
|
|
2019-07-31 23:06:59 +08:00
|
|
|
* :attr:`~django.contrib.auth.models.CustomUser.REQUIRED_FIELDS` now supports
|
|
|
|
:class:`~django.db.models.ManyToManyField`\s.
|
|
|
|
|
2016-08-26 00:26:18 +08:00
|
|
|
* The new :meth:`.UserManager.with_perm` method returns users that have the
|
|
|
|
specified permission.
|
|
|
|
|
2019-09-12 17:48:41 +08:00
|
|
|
* The default iteration count for the PBKDF2 password hasher is increased from
|
|
|
|
150,000 to 180,000.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
:mod:`django.contrib.gis`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-01-19 22:28:42 +08:00
|
|
|
* Allowed MySQL spatial lookup functions to operate on real geometries.
|
|
|
|
Previous support was limited to bounding boxes.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-21 00:54:42 +08:00
|
|
|
* Added the :class:`~django.contrib.gis.db.models.functions.GeometryDistance`
|
|
|
|
function, supported on PostGIS.
|
|
|
|
|
2019-04-09 02:17:05 +08:00
|
|
|
* Added support for the ``furlong`` unit in
|
|
|
|
:class:`~django.contrib.gis.measure.Distance`.
|
|
|
|
|
2019-08-10 17:55:22 +08:00
|
|
|
* The :setting:`GEOIP_PATH` setting now supports :class:`pathlib.Path`.
|
|
|
|
|
|
|
|
* The :class:`~django.contrib.gis.geoip2.GeoIP2` class now accepts
|
|
|
|
:class:`pathlib.Path` ``path``.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
:mod:`django.contrib.postgres`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-07-12 19:08:00 +08:00
|
|
|
* The new :class:`~django.contrib.postgres.fields.RangeOperators` helps to
|
|
|
|
avoid typos in SQL operators that can be used together with
|
|
|
|
:class:`~django.contrib.postgres.fields.RangeField`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-07-12 19:08:00 +08:00
|
|
|
* The new :class:`~django.contrib.postgres.fields.RangeBoundary` expression
|
|
|
|
represents the range boundaries.
|
|
|
|
|
2019-07-25 19:44:18 +08:00
|
|
|
* The new :class:`~django.contrib.postgres.operations.AddIndexConcurrently`
|
|
|
|
and :class:`~django.contrib.postgres.operations.RemoveIndexConcurrently`
|
|
|
|
classes allow creating and dropping indexes ``CONCURRENTLY`` on PostgreSQL.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
:mod:`django.contrib.sessions`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-05-20 04:15:45 +08:00
|
|
|
* The new
|
|
|
|
:meth:`~django.contrib.sessions.backends.base.SessionBase.get_session_cookie_age()`
|
2019-09-10 15:58:42 +08:00
|
|
|
method allows dynamically specifying the session cookie age.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
:mod:`django.contrib.syndication`
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-04-11 05:48:58 +08:00
|
|
|
* Added the ``language`` class attribute to the
|
|
|
|
:class:`django.contrib.syndication.views.Feed` to customize a feed language.
|
|
|
|
The default value is :func:`~django.utils.translation.get_language()` instead
|
2019-05-21 14:21:35 +08:00
|
|
|
of :setting:`LANGUAGE_CODE`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
Cache
|
|
|
|
~~~~~
|
|
|
|
|
2019-06-25 14:15:00 +08:00
|
|
|
* :func:`~django.utils.cache.add_never_cache_headers` and
|
2019-10-10 20:22:04 +08:00
|
|
|
:func:`~django.views.decorators.cache.never_cache` now add the ``private``
|
|
|
|
directive to ``Cache-Control`` headers.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
File Storage
|
|
|
|
~~~~~~~~~~~~
|
|
|
|
|
2019-08-29 00:17:07 +08:00
|
|
|
* The new :meth:`.Storage.get_alternative_name` method allows customizing the
|
|
|
|
algorithm for generating filenames if a file with the uploaded name already
|
|
|
|
exists.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
Forms
|
|
|
|
~~~~~
|
|
|
|
|
2018-11-22 04:58:04 +08:00
|
|
|
* Formsets may control the widget used when ordering forms via
|
|
|
|
:attr:`~django.forms.formsets.BaseFormSet.can_order` by setting the
|
|
|
|
:attr:`~django.forms.formsets.BaseFormSet.ordering_widget` attribute or
|
|
|
|
overriding :attr:`~django.forms.formsets.BaseFormSet.get_ordering_widget()`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
|
|
|
Internationalization
|
|
|
|
~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-04-01 17:29:10 +08:00
|
|
|
* Added the :setting:`LANGUAGE_COOKIE_HTTPONLY`,
|
|
|
|
:setting:`LANGUAGE_COOKIE_SAMESITE`, and :setting:`LANGUAGE_COOKIE_SECURE`
|
|
|
|
settings to set the ``HttpOnly``, ``SameSite``, and ``Secure`` flags on
|
|
|
|
language cookies. The default values of these settings preserve the previous
|
|
|
|
behavior.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-09-28 04:43:36 +08:00
|
|
|
* Added support and translations for the Uzbek language.
|
|
|
|
|
2019-02-24 23:10:14 +08:00
|
|
|
Logging
|
|
|
|
~~~~~~~
|
|
|
|
|
|
|
|
* The new ``reporter_class`` parameter of
|
|
|
|
:class:`~django.utils.log.AdminEmailHandler` allows providing an
|
|
|
|
``django.views.debug.ExceptionReporter`` subclass to customize the traceback
|
|
|
|
text sent to site :setting:`ADMINS` when :setting:`DEBUG` is ``False``.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Management Commands
|
|
|
|
~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-01-28 03:35:17 +08:00
|
|
|
* The new :option:`compilemessages --ignore` option allows ignoring specific
|
|
|
|
directories when searching for ``.po`` files to compile.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-08 00:52:10 +08:00
|
|
|
* :option:`showmigrations --list` now shows the applied datetimes when
|
|
|
|
``--verbosity`` is 2 and above.
|
|
|
|
|
2019-04-16 17:40:22 +08:00
|
|
|
* On PostgreSQL, :djadmin:`dbshell` now supports client-side TLS certificates.
|
|
|
|
|
2019-04-25 21:45:00 +08:00
|
|
|
* :djadmin:`inspectdb` now introspects :class:`~django.db.models.OneToOneField`
|
|
|
|
when a foreign key has a unique or primary key constraint.
|
|
|
|
|
2019-04-27 07:37:57 +08:00
|
|
|
* The new :option:`--skip-checks` option skips running system checks prior to
|
|
|
|
running the command.
|
|
|
|
|
2019-02-06 06:00:56 +08:00
|
|
|
* The :option:`startapp --template` and :option:`startproject --template`
|
|
|
|
options now support templates stored in XZ archives (``.tar.xz``, ``.txz``)
|
|
|
|
and LZMA archives (``.tar.lzma``, ``.tlz``).
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Models
|
|
|
|
~~~~~~
|
|
|
|
|
2019-03-21 02:30:43 +08:00
|
|
|
* Added hash database functions :class:`~django.db.models.functions.MD5`,
|
|
|
|
:class:`~django.db.models.functions.SHA1`,
|
|
|
|
:class:`~django.db.models.functions.SHA224`,
|
|
|
|
:class:`~django.db.models.functions.SHA256`,
|
|
|
|
:class:`~django.db.models.functions.SHA384`, and
|
|
|
|
:class:`~django.db.models.functions.SHA512`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-20 16:27:34 +08:00
|
|
|
* Added the :class:`~django.db.models.functions.Sign` database function.
|
|
|
|
|
2019-03-07 23:02:18 +08:00
|
|
|
* The new ``is_dst`` parameter of the
|
|
|
|
:class:`~django.db.models.functions.Trunc` database functions determines the
|
|
|
|
treatment of nonexistent and ambiguous datetimes.
|
|
|
|
|
2019-04-26 00:09:27 +08:00
|
|
|
* ``connection.queries`` now shows ``COPY … TO`` statements on PostgreSQL.
|
|
|
|
|
2019-09-10 15:58:42 +08:00
|
|
|
* :class:`~django.db.models.FilePathField` now accepts a callable for ``path``.
|
2019-05-02 16:42:10 +08:00
|
|
|
|
2019-04-20 00:12:04 +08:00
|
|
|
* Allowed symmetrical intermediate table for self-referential
|
|
|
|
:class:`~django.db.models.ManyToManyField`.
|
|
|
|
|
2019-07-05 20:15:41 +08:00
|
|
|
* The ``name`` attributes of :class:`~django.db.models.CheckConstraint`,
|
|
|
|
:class:`~django.db.models.UniqueConstraint`, and
|
|
|
|
:class:`~django.db.models.Index` now support app label and class
|
|
|
|
interpolation using the ``'%(app_label)s'`` and ``'%(class)s'`` placeholders.
|
|
|
|
|
2019-07-23 20:04:06 +08:00
|
|
|
* The new :attr:`.Field.descriptor_class` attribute allows model fields to
|
|
|
|
customize the get and set behavior by overriding their
|
|
|
|
:py:ref:`descriptors <descriptors>`.
|
|
|
|
|
2019-07-31 02:08:55 +08:00
|
|
|
* :class:`~django.db.models.Avg` and :class:`~django.db.models.Sum` now support
|
|
|
|
the ``distinct`` argument.
|
|
|
|
|
2019-07-27 05:05:22 +08:00
|
|
|
* Added :class:`~django.db.models.SmallAutoField` which acts much like an
|
|
|
|
:class:`~django.db.models.AutoField` except that it only allows values under
|
|
|
|
a certain (database-dependent) limit. Values from ``1`` to ``32767`` are safe
|
|
|
|
in all databases supported by Django.
|
|
|
|
|
2017-12-11 23:36:33 +08:00
|
|
|
* :class:`~django.db.models.AutoField`,
|
|
|
|
:class:`~django.db.models.BigAutoField`, and
|
|
|
|
:class:`~django.db.models.SmallAutoField` now inherit from
|
|
|
|
``IntegerField``, ``BigIntegerField`` and ``SmallIntegerField`` respectively.
|
|
|
|
System checks and validators are now also properly inherited.
|
|
|
|
|
2019-08-18 17:40:11 +08:00
|
|
|
* :attr:`.FileField.upload_to` now supports :class:`pathlib.Path`.
|
|
|
|
|
2019-09-04 22:54:27 +08:00
|
|
|
* :class:`~django.db.models.CheckConstraint` is now supported on MySQL 8.0.16+.
|
|
|
|
|
2019-07-29 22:40:27 +08:00
|
|
|
* The new ``allows_group_by_selected_pks_on_model()`` method of
|
|
|
|
``django.db.backends.base.BaseDatabaseFeatures`` allows optimization of
|
|
|
|
``GROUP BY`` clauses to require only the selected models' primary keys. By
|
|
|
|
default, it's supported only for managed models on PostgreSQL.
|
|
|
|
|
|
|
|
To enable the ``GROUP BY`` primary key-only optimization for unmanaged
|
|
|
|
models, you have to subclass the PostgreSQL database engine, overriding the
|
|
|
|
features class ``allows_group_by_selected_pks_on_model()`` method as you
|
|
|
|
require. See :ref:`Subclassing the built-in database backends
|
|
|
|
<subclassing-database-backends>` for an example.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Requests and Responses
|
|
|
|
~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
|
2019-03-27 12:40:10 +08:00
|
|
|
* Allowed :class:`~django.http.HttpResponse` to be initialized with
|
|
|
|
:class:`memoryview` content.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-05-09 22:26:52 +08:00
|
|
|
* For use in, for example, Django templates, :attr:`.HttpRequest.headers` now
|
2019-12-12 17:19:09 +08:00
|
|
|
allows lookups using underscores (e.g. ``user_agent``) in place of hyphens.
|
2019-05-09 22:26:52 +08:00
|
|
|
|
2019-09-02 07:19:16 +08:00
|
|
|
.. _whats-new-security-3.0:
|
|
|
|
|
|
|
|
Security
|
|
|
|
~~~~~~~~
|
|
|
|
|
|
|
|
* :setting:`X_FRAME_OPTIONS` now defaults to ``'DENY'``. In older versions, the
|
|
|
|
:setting:`X_FRAME_OPTIONS` setting defaults to ``'SAMEORIGIN'``. If your site
|
2019-12-04 16:22:51 +08:00
|
|
|
uses frames of itself, you will need to explicitly set ``X_FRAME_OPTIONS =
|
2019-09-02 07:19:16 +08:00
|
|
|
'SAMEORIGIN'`` for them to continue working.
|
|
|
|
|
2020-02-05 19:46:14 +08:00
|
|
|
* :setting:`SECURE_CONTENT_TYPE_NOSNIFF` now defaults to ``True``. With this
|
|
|
|
enabled, :class:`~django.middleware.security.SecurityMiddleware` sets the
|
2019-09-02 07:19:16 +08:00
|
|
|
:ref:`x-content-type-options` header on all responses that do not already
|
|
|
|
have it.
|
|
|
|
|
2019-03-22 05:33:41 +08:00
|
|
|
* :class:`~django.middleware.security.SecurityMiddleware` can now send the
|
|
|
|
:ref:`Referrer-Policy <referrer-policy>` header.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Tests
|
|
|
|
~~~~~
|
|
|
|
|
2019-02-20 19:16:10 +08:00
|
|
|
* The new test :class:`~django.test.Client` argument
|
|
|
|
``raise_request_exception`` allows controlling whether or not exceptions
|
|
|
|
raised during the request should also be raised in the test. The value
|
|
|
|
defaults to ``True`` for backwards compatibility. If it is ``False`` and an
|
|
|
|
exception occurs, the test client will return a 500 response with the
|
|
|
|
attribute :attr:`~django.test.Response.exc_info`, a tuple providing
|
|
|
|
information of the exception that occurred.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-03-08 04:58:30 +08:00
|
|
|
* Tests and test cases to run can be selected by test name pattern using the
|
|
|
|
new :option:`test -k` option.
|
|
|
|
|
2019-05-09 21:55:32 +08:00
|
|
|
* HTML comparison, as used by
|
|
|
|
:meth:`~django.test.SimpleTestCase.assertHTMLEqual`, now treats text, character
|
|
|
|
references, and entity references that refer to the same character as
|
|
|
|
equivalent.
|
|
|
|
|
2019-02-27 00:23:49 +08:00
|
|
|
* Django test runner now supports headless mode for selenium tests on supported
|
|
|
|
browsers. Add the ``--headless`` option to enable this mode.
|
|
|
|
|
2019-05-26 02:55:30 +08:00
|
|
|
* Django test runner now supports ``--start-at`` and ``--start-after`` options
|
|
|
|
to run tests starting from a specific top-level module.
|
|
|
|
|
2019-08-05 11:41:14 +08:00
|
|
|
* Django test runner now supports a ``--pdb`` option to spawn a debugger at
|
|
|
|
each error or failure.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
.. _backwards-incompatible-3.0:
|
|
|
|
|
|
|
|
Backwards incompatible changes in 3.0
|
|
|
|
=====================================
|
|
|
|
|
2019-12-12 12:09:38 +08:00
|
|
|
``Model.save()`` when providing a default for the primary key
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
:meth:`.Model.save` no longer attempts to find a row when saving a new
|
|
|
|
``Model`` instance and a default value for the primary key is provided, and
|
|
|
|
always performs a single ``INSERT`` query. In older Django versions,
|
|
|
|
``Model.save()`` performed either an ``INSERT`` or an ``UPDATE`` based on
|
|
|
|
whether or not the row exists.
|
|
|
|
|
|
|
|
This makes calling ``Model.save()`` while providing a default primary key value
|
|
|
|
equivalent to passing :ref:`force_insert=True <ref-models-force-insert>` to
|
|
|
|
model's ``save()``. Attempts to use a new ``Model`` instance to update an
|
|
|
|
existing row will result in an ``IntegrityError``.
|
|
|
|
|
|
|
|
In order to update an existing model for a specific primary key value, use the
|
|
|
|
:meth:`~django.db.models.query.QuerySet.update_or_create` method or
|
|
|
|
``QuerySet.filter(pk=…).update(…)`` instead. For example::
|
|
|
|
|
|
|
|
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={'name': 'new name'})
|
|
|
|
>>> MyModel.objects.filter(pk=existing_pk).update(name='new name')
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Database backend API
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
This section describes changes that may be needed in third-party database
|
|
|
|
backends.
|
|
|
|
|
2019-01-19 22:00:24 +08:00
|
|
|
* The second argument of ``DatabaseIntrospection.get_geometry_type()`` is now
|
|
|
|
the row description instead of the column name.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2019-01-19 21:35:51 +08:00
|
|
|
* ``DatabaseIntrospection.get_field_type()`` may no longer return tuples.
|
|
|
|
|
2019-01-19 12:17:26 +08:00
|
|
|
* If the database can create foreign keys in the same SQL statement that adds a
|
|
|
|
field, add ``SchemaEditor.sql_create_column_inline_fk`` with the appropriate
|
|
|
|
SQL; otherwise, set ``DatabaseFeatures.can_create_inline_fk = False``.
|
|
|
|
|
2019-01-31 04:31:56 +08:00
|
|
|
* ``DatabaseFeatures.can_return_id_from_insert`` and
|
|
|
|
``can_return_ids_from_bulk_insert`` are renamed to
|
|
|
|
``can_return_columns_from_insert`` and ``can_return_rows_from_bulk_insert``.
|
|
|
|
|
2019-06-12 21:35:06 +08:00
|
|
|
* Database functions now handle :class:`datetime.timezone` formats when created
|
|
|
|
using :class:`datetime.timedelta` instances (e.g.
|
|
|
|
``timezone(timedelta(hours=5))``, which would output ``'UTC+05:00'``).
|
|
|
|
Third-party backends should handle this format when preparing
|
|
|
|
:class:`~django.db.models.DateTimeField` in ``datetime_cast_date_sql()``,
|
|
|
|
``datetime_extract_sql()``, etc.
|
|
|
|
|
2017-12-11 23:36:33 +08:00
|
|
|
* Entries for ``AutoField``, ``BigAutoField``, and ``SmallAutoField`` are added
|
|
|
|
to ``DatabaseOperations.integer_field_ranges`` to support the integer range
|
|
|
|
validators on these field types. Third-party backends may need to customize
|
|
|
|
the default entries.
|
|
|
|
|
2019-07-24 14:42:41 +08:00
|
|
|
* ``DatabaseOperations.fetch_returned_insert_id()`` is replaced by
|
|
|
|
``fetch_returned_insert_columns()`` which returns a list of values returned
|
|
|
|
by the ``INSERT … RETURNING`` statement, instead of a single value.
|
|
|
|
|
|
|
|
* ``DatabaseOperations.return_insert_id()`` is replaced by
|
|
|
|
``return_insert_columns()`` that accepts a ``fields``
|
|
|
|
argument, which is an iterable of fields to be returned after insert. Usually
|
|
|
|
this is only the auto-generated primary key.
|
|
|
|
|
2019-06-15 00:20:29 +08:00
|
|
|
:mod:`django.contrib.admin`
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
* Admin's model history change messages now prefers more readable field labels
|
|
|
|
instead of field names.
|
|
|
|
|
2019-02-05 01:03:12 +08:00
|
|
|
:mod:`django.contrib.gis`
|
|
|
|
-------------------------
|
|
|
|
|
2019-02-11 00:45:03 +08:00
|
|
|
* Support for PostGIS 2.1 is removed.
|
2019-02-05 00:07:46 +08:00
|
|
|
|
2019-02-05 01:03:12 +08:00
|
|
|
* Support for SpatiaLite 4.1 and 4.2 is removed.
|
|
|
|
|
2019-02-09 21:40:55 +08:00
|
|
|
* Support for GDAL 1.11 and GEOS 3.4 is removed.
|
2019-02-08 08:10:34 +08:00
|
|
|
|
2019-02-05 00:07:46 +08:00
|
|
|
Dropped support for PostgreSQL 9.4
|
|
|
|
----------------------------------
|
|
|
|
|
|
|
|
Upstream support for PostgreSQL 9.4 ends in December 2019. Django 3.0 supports
|
|
|
|
PostgreSQL 9.5 and higher.
|
|
|
|
|
2019-02-07 02:25:04 +08:00
|
|
|
Dropped support for Oracle 12.1
|
|
|
|
-------------------------------
|
|
|
|
|
|
|
|
Upstream support for Oracle 12.1 ends in July 2021. Django 2.2 will be
|
|
|
|
supported until April 2022. Django 3.0 officially supports Oracle 12.2 and 18c.
|
|
|
|
|
2019-02-05 03:00:00 +08:00
|
|
|
Removed private Python 2 compatibility APIs
|
|
|
|
-------------------------------------------
|
|
|
|
|
|
|
|
While Python 2 support was removed in Django 2.0, some private APIs weren't
|
|
|
|
removed from Django so that third party apps could continue using them until
|
|
|
|
the Python 2 end-of-life.
|
|
|
|
|
|
|
|
Since we expect apps to drop Python 2 compatibility when adding support for
|
|
|
|
Django 3.0, we're removing these APIs at this time.
|
|
|
|
|
|
|
|
* ``django.test.utils.str_prefix()`` - Strings don't have 'u' prefixes in
|
|
|
|
Python 3.
|
|
|
|
|
|
|
|
* ``django.test.utils.patch_logger()`` - Use
|
|
|
|
:meth:`unittest.TestCase.assertLogs` instead.
|
|
|
|
|
2019-02-05 08:40:07 +08:00
|
|
|
* ``django.utils.lru_cache.lru_cache()`` - Alias of
|
|
|
|
:func:`functools.lru_cache`.
|
|
|
|
|
2019-02-05 08:44:54 +08:00
|
|
|
* ``django.utils.decorators.available_attrs()`` - This function returns
|
|
|
|
``functools.WRAPPER_ASSIGNMENTS``.
|
|
|
|
|
2019-02-05 09:14:46 +08:00
|
|
|
* ``django.utils.decorators.ContextDecorator`` - Alias of
|
|
|
|
:class:`contextlib.ContextDecorator`.
|
|
|
|
|
2019-02-05 08:50:30 +08:00
|
|
|
* ``django.utils._os.abspathu()`` - Alias of :func:`os.path.abspath`.
|
|
|
|
|
|
|
|
* ``django.utils._os.upath()`` and ``npath()`` - These functions do nothing on
|
|
|
|
Python 3.
|
|
|
|
|
2019-02-05 08:53:27 +08:00
|
|
|
* ``django.utils.six`` - Remove usage of this vendored library or switch to
|
|
|
|
`six <https://pypi.org/project/six/>`_.
|
|
|
|
|
|
|
|
* ``django.utils.encoding.python_2_unicode_compatible()`` - Alias of
|
|
|
|
``six.python_2_unicode_compatible()``.
|
|
|
|
|
2019-02-05 09:22:44 +08:00
|
|
|
* ``django.utils.functional.curry()`` - Use :func:`functools.partial` or
|
2021-04-29 02:37:36 +08:00
|
|
|
:class:`functools.partialmethod`. See
|
|
|
|
:commit:`5b1c389603a353625ae1603ba345147356336afb`.
|
2019-02-05 09:22:44 +08:00
|
|
|
|
2019-02-05 21:19:49 +08:00
|
|
|
* ``django.utils.safestring.SafeBytes`` - Unused since Django 2.0.
|
|
|
|
|
2019-02-06 21:57:37 +08:00
|
|
|
New default value for the ``FILE_UPLOAD_PERMISSIONS`` setting
|
|
|
|
-------------------------------------------------------------
|
|
|
|
|
|
|
|
In older versions, the :setting:`FILE_UPLOAD_PERMISSIONS` setting defaults to
|
|
|
|
``None``. With the default :setting:`FILE_UPLOAD_HANDLERS`, this results in
|
|
|
|
uploaded files having different permissions depending on their size and which
|
|
|
|
upload handler is used.
|
|
|
|
|
2020-08-21 15:47:37 +08:00
|
|
|
``FILE_UPLOAD_PERMISSIONS`` now defaults to ``0o644`` to avoid this
|
2019-02-06 21:57:37 +08:00
|
|
|
inconsistency.
|
|
|
|
|
2019-09-02 07:19:16 +08:00
|
|
|
New default values for security settings
|
|
|
|
----------------------------------------
|
2019-09-07 15:52:10 +08:00
|
|
|
|
2019-09-02 07:19:16 +08:00
|
|
|
To make Django projects more secure by default, some security settings now have
|
|
|
|
more secure default values:
|
|
|
|
|
|
|
|
* :setting:`X_FRAME_OPTIONS` now defaults to ``'DENY'``.
|
|
|
|
|
|
|
|
* :setting:`SECURE_CONTENT_TYPE_NOSNIFF` now defaults to ``True``.
|
|
|
|
|
|
|
|
See the *What's New* :ref:`Security section <whats-new-security-3.0>` above for
|
|
|
|
more details on these changes.
|
2019-09-07 15:52:10 +08:00
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Miscellaneous
|
|
|
|
-------------
|
|
|
|
|
2018-12-21 15:24:04 +08:00
|
|
|
* ``ContentType.__str__()`` now includes the model's ``app_label`` to
|
2019-12-05 14:55:20 +08:00
|
|
|
disambiguate models with the same name in different apps.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2016-08-15 04:42:49 +08:00
|
|
|
* Because accessing the language in the session rather than in the cookie is
|
|
|
|
deprecated, ``LocaleMiddleware`` no longer looks for the user's language in
|
|
|
|
the session and :func:`django.contrib.auth.logout` no longer preserves the
|
|
|
|
session's language after logout.
|
|
|
|
|
2019-04-24 19:30:34 +08:00
|
|
|
* :func:`django.utils.html.escape` now uses :func:`html.escape` to escape HTML.
|
|
|
|
This converts ``'`` to ``'`` instead of the previous equivalent decimal
|
|
|
|
code ``'``.
|
|
|
|
|
2019-03-08 04:58:30 +08:00
|
|
|
* The ``django-admin test -k`` option now works as the :option:`unittest
|
|
|
|
-k<unittest.-k>` option rather than as a shortcut for ``--keepdb``.
|
|
|
|
|
2019-04-30 04:51:05 +08:00
|
|
|
* Support for ``pywatchman`` < 1.2.0 is removed.
|
|
|
|
|
2019-05-24 23:15:34 +08:00
|
|
|
* :func:`~django.utils.http.urlencode` now encodes iterable values as they are
|
|
|
|
when ``doseq=False``, rather than iterating them, bringing it into line with
|
|
|
|
the standard library :func:`urllib.parse.urlencode` function.
|
|
|
|
|
2019-06-10 03:48:20 +08:00
|
|
|
* ``intword`` template filter now translates ``1.0`` as a singular phrase and
|
|
|
|
all other numeric values as plural. This may be incorrect for some languages.
|
|
|
|
|
2019-07-23 20:04:06 +08:00
|
|
|
* Assigning a value to a model's :class:`~django.db.models.ForeignKey` or
|
|
|
|
:class:`~django.db.models.OneToOneField` ``'_id'`` attribute now unsets the
|
|
|
|
corresponding field. Accessing the field afterwards will result in a query.
|
|
|
|
|
2019-08-14 04:40:09 +08:00
|
|
|
* :func:`~django.utils.cache.patch_vary_headers` now handles an asterisk
|
|
|
|
``'*'`` according to :rfc:`7231#section-7.1.4`, i.e. if a list of header
|
|
|
|
field names contains an asterisk, then the ``Vary`` header will consist of a
|
|
|
|
single asterisk ``'*'``.
|
|
|
|
|
2019-09-04 22:54:27 +08:00
|
|
|
* On MySQL 8.0.16+, ``PositiveIntegerField`` and ``PositiveSmallIntegerField``
|
|
|
|
now include a check constraint to prevent negative values in the database.
|
|
|
|
|
2019-09-05 21:56:52 +08:00
|
|
|
* ``alias=None`` is added to the signature of
|
|
|
|
:meth:`.Expression.get_group_by_cols`.
|
|
|
|
|
2019-12-11 18:57:27 +08:00
|
|
|
* ``RegexPattern``, used by :func:`~django.urls.re_path`, no longer returns
|
|
|
|
keyword arguments with ``None`` values to be passed to the view for the
|
|
|
|
optional named groups that are missing.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
.. _deprecated-features-3.0:
|
|
|
|
|
|
|
|
Features deprecated in 3.0
|
|
|
|
==========================
|
|
|
|
|
2019-02-05 22:19:49 +08:00
|
|
|
``django.utils.encoding.force_text()`` and ``smart_text()``
|
|
|
|
-----------------------------------------------------------
|
|
|
|
|
|
|
|
The ``smart_text()`` and ``force_text()`` aliases (since Django 2.0) of
|
|
|
|
``smart_str()`` and ``force_str()`` are deprecated. Ignore this deprecation if
|
|
|
|
your code supports Python 2 as the behavior of ``smart_str()`` and
|
|
|
|
``force_str()`` is different there.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
Miscellaneous
|
|
|
|
-------------
|
|
|
|
|
2019-02-05 07:53:11 +08:00
|
|
|
* ``django.utils.http.urlquote()``, ``urlquote_plus()``, ``urlunquote()``, and
|
|
|
|
``urlunquote_plus()`` are deprecated in favor of the functions that they're
|
|
|
|
aliases for: :func:`urllib.parse.quote`, :func:`~urllib.parse.quote_plus`,
|
|
|
|
:func:`~urllib.parse.unquote`, and :func:`~urllib.parse.unquote_plus`.
|
|
|
|
|
2019-02-06 11:45:26 +08:00
|
|
|
* ``django.utils.translation.ugettext()``, ``ugettext_lazy()``,
|
|
|
|
``ugettext_noop()``, ``ungettext()``, and ``ungettext_lazy()`` are deprecated
|
|
|
|
in favor of the functions that they're aliases for:
|
|
|
|
:func:`django.utils.translation.gettext`,
|
|
|
|
:func:`~django.utils.translation.gettext_lazy`,
|
|
|
|
:func:`~django.utils.translation.gettext_noop`,
|
|
|
|
:func:`~django.utils.translation.ngettext`, and
|
|
|
|
:func:`~django.utils.translation.ngettext_lazy`.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2016-08-15 04:42:49 +08:00
|
|
|
* To limit creation of sessions and hence favor some caching strategies,
|
|
|
|
:func:`django.views.i18n.set_language` will stop setting the user's language
|
|
|
|
in the session in Django 4.0. Since Django 2.1, the language is always stored
|
|
|
|
in the :setting:`LANGUAGE_COOKIE_NAME` cookie.
|
|
|
|
|
2019-04-24 21:10:28 +08:00
|
|
|
* ``django.utils.text.unescape_entities()`` is deprecated in favor of
|
|
|
|
:func:`html.unescape`. Note that unlike ``unescape_entities()``,
|
|
|
|
``html.unescape()`` evaluates lazy strings immediately.
|
|
|
|
|
2019-08-14 23:39:21 +08:00
|
|
|
* To avoid possible confusion as to effective scope, the private internal
|
|
|
|
utility ``is_safe_url()`` is renamed to
|
|
|
|
``url_has_allowed_host_and_scheme()``. That a URL has an allowed host and
|
|
|
|
scheme doesn't in general imply that it's "safe". It may still be quoted
|
|
|
|
incorrectly, for example. Ensure to also use
|
|
|
|
:func:`~django.utils.encoding.iri_to_uri` on the path component of untrusted
|
|
|
|
URLs.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
.. _removed-features-3.0:
|
|
|
|
|
|
|
|
Features removed in 3.0
|
|
|
|
=======================
|
|
|
|
|
|
|
|
These features have reached the end of their deprecation cycle and are removed
|
|
|
|
in Django 3.0.
|
|
|
|
|
|
|
|
See :ref:`deprecated-features-2.0` for details on these changes, including how
|
|
|
|
to remove usage of these features.
|
|
|
|
|
2018-12-28 08:23:09 +08:00
|
|
|
* The ``django.db.backends.postgresql_psycopg2`` module is removed.
|
2018-12-28 08:03:30 +08:00
|
|
|
|
2018-12-28 08:23:09 +08:00
|
|
|
* ``django.shortcuts.render_to_response()`` is removed.
|
|
|
|
|
2018-12-28 08:49:03 +08:00
|
|
|
* The ``DEFAULT_CONTENT_TYPE`` setting is removed.
|
|
|
|
|
2018-12-28 08:58:22 +08:00
|
|
|
* ``HttpRequest.xreadlines()`` is removed.
|
|
|
|
|
2018-12-28 08:58:22 +08:00
|
|
|
* Support for the ``context`` argument of ``Field.from_db_value()`` and
|
|
|
|
``Expression.convert_value()`` is removed.
|
|
|
|
|
2019-03-07 18:10:17 +08:00
|
|
|
* The ``field_name`` keyword argument of ``QuerySet.earliest()`` and
|
2018-12-28 09:18:45 +08:00
|
|
|
``latest()`` is removed.
|
|
|
|
|
2018-12-28 08:03:30 +08:00
|
|
|
See :ref:`deprecated-features-2.1` for details on these changes, including how
|
|
|
|
to remove usage of these features.
|
|
|
|
|
2018-12-28 09:31:55 +08:00
|
|
|
* The ``ForceRHR`` GIS function is removed.
|
2018-12-28 09:35:20 +08:00
|
|
|
|
|
|
|
* ``django.utils.http.cookie_date()`` is removed.
|
2018-12-28 09:41:54 +08:00
|
|
|
|
|
|
|
* The ``staticfiles`` and ``admin_static`` template tag libraries are removed.
|
|
|
|
|
|
|
|
* ``django.contrib.staticfiles.templatetags.staticfiles.static()`` is removed.
|