12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145 |
- =============================================
- 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.
- * The new :attr:`InlineModelAdmin.classes
- <django.contrib.admin.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.
- * Selected objects for fields in ``ModelAdmin.raw_id_fields`` now have a link
- to object's change form.
- * Added "No date" and "Has date" choices for ``DateFieldListFilter`` if the
- field is nullable.
- :mod:`django.contrib.admindocs`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ...
- :mod:`django.contrib.auth`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~
- * Added support for the :ref:`Argon2 password hash <argon2_usage>`. It's
- recommended over PBKDF2, however, it's not the default as it requires a
- third-party library.
- * 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.
- * The new :setting:`LOGOUT_REDIRECT_URL` setting controls the redirect of the
- :func:`~django.contrib.auth.views.logout` view, if the view doesn't get a
- ``next_page`` argument.
- * The new ``redirect_authenticated_user`` parameter for the
- :func:`~django.contrib.auth.views.login` view allows redirecting
- authenticated users visiting the login page.
- :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.
- * 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
- <django.contrib.gis.geos.LineString.closed>` and
- :attr:`MultiLineString.closed
- <django.contrib.gis.geos.MultiLineString.closed>` properties.
- * The :doc:`GeoJSON serializer </ref/contrib/gis/serializers>` now outputs the
- primary key of objects in the ``properties`` dictionary if specific fields
- aren't specified.
- * The ability to replicate input data on the :meth:`GDALBand.data()
- <django.contrib.gis.gdal.GDALBand.data>` method was added. Band data can
- now be updated with repeated values efficiently.
- * Added database functions
- :class:`~django.contrib.gis.db.models.functions.IsValid` and
- :class:`~django.contrib.gis.db.models.functions.MakeValid`, as well as the
- :lookup:`isvalid` lookup, all for PostGIS. This allows filtering and
- repairing invalid geometries on the database side.
- :mod:`django.contrib.messages`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * ...
- :mod:`django.contrib.postgres`
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- * For convenience, :class:`~django.contrib.postgres.fields.HStoreField` now
- casts its keys and values to strings.
- :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
- ~~~~~~~~~~~~~~~~~
- * Temporal data subtraction was unified on all backends.
- * If the database supports it, backends can set
- ``DatabaseFeatures.can_return_ids_from_bulk_insert=True`` and implement
- ``DatabaseOperations.fetch_returned_insert_ids()`` to set primary keys
- on objects created using ``QuerySet.bulk_create()``.
- * Added keyword arguments to the ``as_sql()`` methods of various expressions
- (``Func``, ``When``, ``Case``, and ``OrderBy``) to allow database backends to
- customize them without mutating ``self``, which isn't safe when using
- different database backends. See the ``arg_joiner`` and ``**extra_context``
- parameters of :meth:`Func.as_sql() <django.db.models.Func.as_sql>` for an
- example.
- Email
- ~~~~~
- * ...
- File Storage
- ~~~~~~~~~~~~
- * Storage backends now present a timezone-aware API with new methods
- :meth:`~django.core.files.storage.Storage.get_accessed_time`,
- :meth:`~django.core.files.storage.Storage.get_created_time`, and
- :meth:`~django.core.files.storage.Storage.get_modified_time`. They return a
- timezone-aware ``datetime`` if :setting:`USE_TZ` is ``True`` and a naive
- ``datetime`` in the local timezone otherwise.
- File Uploads
- ~~~~~~~~~~~~
- * ...
- Forms
- ~~~~~
- * Form and widget ``Media`` is now served using
- :mod:`django.contrib.staticfiles` if installed.
- * The ``<input>`` tag rendered by :class:`~django.forms.CharField` now includes
- a ``minlength`` attribute if the field has a ``min_length``.
- * Required form fields now have the ``required`` HTML attribute. Set the new
- :attr:`Form.use_required_attribute <django.forms.Form.use_required_attribute>`
- attribute to ``False`` to disable it. The ``required`` attribute isn't
- included on forms of formsets because the browser validation may not be
- correct when adding and deleting formsets.
- Generic Views
- ~~~~~~~~~~~~~
- * The :class:`~django.views.generic.base.View` class can now be imported from
- ``django.views``.
- Internationalization
- ~~~~~~~~~~~~~~~~~~~~
- * The :func:`~django.conf.urls.i18n.i18n_patterns` helper function can now be
- used in a root URLConf specified using :attr:`request.urlconf
- <django.http.HttpRequest.urlconf>`.
- * By setting the new ``prefix_default_language`` parameter for
- :func:`~django.conf.urls.i18n.i18n_patterns` to ``False``, you can allow
- accessing the default language without a URL prefix.
- * :func:`~django.views.i18n.set_language` now returns a 204 status code (No
- Content) for AJAX requests when there is no ``next`` parameter in ``POST`` or
- ``GET``.
- * The :class:`~django.views.i18n.JavaScriptCatalog` and
- :class:`~django.views.i18n.JSONCatalog` class-based views supersede the
- deprecated ``javascript_catalog()`` and ``json_catalog()`` function-based
- views. The new views are almost equivalent to the old ones except that by
- default the new views collect all JavaScript strings in the ``djangojs``
- translation domain from all installed apps rather than only the JavaScript
- strings from :setting:`LOCALE_PATHS`.
- Management Commands
- ~~~~~~~~~~~~~~~~~~~
- * :func:`~django.core.management.call_command` now returns the value returned
- from the ``command.handle()`` method.
- * The new :option:`check --fail-level` option allows specifying the message
- level that will cause the command to exit with a non-zero status.
- * The new :option:`makemigrations --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 :option:`shell --interface` option now accepts ``python`` to force use of
- the "plain" Python interpreter.
- * The new :option:`shell --command` option lets you run a command as Django and
- exit, instead of opening the interactive shell.
- * Added a warning to :djadmin:`dumpdata` if a proxy model is specified (which
- results in no output) without its concrete parent.
- * The new :attr:`BaseCommand.requires_migrations_checks
- <django.core.management.BaseCommand.requires_migrations_checks>` attribute
- may be set to ``True`` if you want your command to print a warning, like
- :djadmin:`runserver` does, if the set of migrations on disk don't match the
- migrations in the database.
- * To assist with testing, :func:`~django.core.management.call_command` now
- accepts a command object as the first argument.
- * The :djadmin:`shell` command supports tab completion on systems using
- ``libedit``, e.g. Mac OSX.
- * The :djadmin:`inspectdb` command lets you choose what tables should be
- inspected by specifying their names as arguments.
- Migrations
- ~~~~~~~~~~
- * Added support for serialization of ``enum.Enum`` objects.
- * Added the ``elidable`` argument to the
- :class:`~django.db.migrations.operations.RunSQL` and
- :class:`~django.db.migrations.operations.RunPython` operations to allow them
- to be removed when squashing migrations.
- * Added support for :ref:`non-atomic migrations <non-atomic-migrations>` by
- setting the ``atomic`` attribute on a ``Migration``.
- * The ``migrate`` and ``makemigrations`` commands now check for a consistent
- migration history. If they find some unapplied dependencies of an applied
- migration, ``InconsistentMigrationHistory`` is raised.
- 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.
- * 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() <django.db.models.query.QuerySet.in_bulk>`
- may be called without any arguments to return all objects in the queryset.
- * :attr:`~django.db.models.ForeignKey.related_query_name` now supports
- app label and class interpolation using the ``'%(app_label)s'`` and
- ``'%(class)s'`` strings.
- * The :func:`~django.db.models.prefetch_related_objects` function is now a
- public API.
- * :meth:`QuerySet.bulk_create() <django.db.models.query.QuerySet.bulk_create>`
- sets the primary key on objects when using PostgreSQL.
- * Added the :class:`~django.db.models.functions.Cast` database function.
- * A proxy model may now inherit multiple proxy models that share a common
- non-abstract parent class.
- 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`.
- * Added the :attr:`HttpResponse.content_type
- <django.http.HttpRequest.content_type>` and
- :attr:`~django.http.HttpRequest.content_params` attributes which are
- parsed from the ``CONTENT_TYPE`` header.
- * The parser for ``request.COOKIES`` is simplified to better match the behavior
- of browsers. ``request.COOKIES`` may now contain cookies that are invalid
- according to :rfc:`6265` but are possible to set via ``document.cookie``.
- 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.
- * Added the ``is`` and ``is not`` comparison operators to the :ttag:`if` tag.
- * Allowed :tfilter:`dictsort` to order a list of lists by an element at a
- specified index.
- * The :func:`~django.template.context_processors.debug` context processor
- contains queries for all database aliases instead of only the default alias.
- Tests
- ~~~~~
- * To better catch bugs, :class:`~django.test.TestCase` now checks deferrable
- database constraints at the end of each test.
- * Tests and test cases can be :ref:`marked with tags <topics-tagging-tests>`
- and run selectively with the new :option:`test --tag` and :option:`test
- --exclude-tag` options.
- * Added the :setting:`DATABASES['TEST']['MIGRATE'] <TEST_MIGRATE>` option to
- allow disabling of migrations during test database creation.
- * You can now login and use sessions with the test client even if
- :mod:`django.contrib.sessions` is not in :setting:`INSTALLED_APPS`.
- 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`.
- * :func:`~django.core.validators.int_list_validator` now accepts an optional
- ``allow_negative`` boolean parameter, defaulting to ``False``, to allow
- negative integers.
- 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
- --------------------
- * GIS's ``AreaField`` uses an unspecified underlying numeric type that could in
- practice be any numeric Python type. ``decimal.Decimal`` values retrieved
- from the database are now converted to ``float`` to make it easier to combine
- them with values used by the GIS libraries.
- * In order to enable temporal subtraction you must set the
- ``supports_temporal_subtraction`` database feature flag to ``True`` and
- implement the ``DatabaseOperations.subtract_temporals()`` method. This
- method should return the SQL and parameters required to compute the
- difference in microseconds between the ``lhs`` and ``rhs`` arguments in the
- datatype used to store :class:`~django.db.models.DurationField`.
- ``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 150
- --------------------------------------------------------------------------------------------------------
- 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.
- We considered an increase to 254 characters to more easily allow the use of
- email addresses (which are limited to 254 characters) as usernames but rejected
- it due to a MySQL limitation. When using the ``utf8mb4`` encoding (recommended
- for proper Unicode support), MySQL can only create unique indexes with 191
- characters by default. Therefore, if you need a longer length, please use a
- custom 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.
- ``runserver`` output goes through logging
- -----------------------------------------
- Request and response handling of the ``runserver`` command is sent to the
- :ref:`django-server-logger` logger instead of to ``sys.stderr``. If you
- disable Django's logging configuration or override it with your own, you'll
- need to add the appropriate logging configuration if you want to see that
- output::
- 'formatters': {
- 'django.server': {
- '()': 'django.utils.log.ServerFormatter',
- 'format': '[%(server_time)s] %(message)s',
- }
- },
- 'handlers': {
- 'django.server': {
- 'level': 'INFO',
- 'class': 'logging.StreamHandler',
- 'formatter': 'django.server',
- },
- },
- 'loggers': {
- 'django.server': {
- 'handlers': ['django.server'],
- 'level': 'INFO',
- 'propagate': False,
- }
- }
- ``auth.CustomUser`` and ``auth.ExtensionUser`` test models were removed
- -----------------------------------------------------------------------
- Since the introduction of migrations for the contrib apps in Django 1.8, the
- tables of these custom user test models were not created anymore making them
- unusable in a testing context.
- Apps registry is no longer auto-populated when unpickling models outside of Django
- ----------------------------------------------------------------------------------
- The apps registry is no longer auto-populated when unpickling models. This was
- added in Django 1.7.2 as an attempt to allow unpickling models outside of
- Django, such as in an RQ worker, without calling ``django.setup()``, but it
- creates the possibility of a deadlock. To adapt your code in the case of RQ,
- you can `provide your own worker script <http://python-rq.org/docs/workers/>`_
- that calls ``django.setup()``.
- Removed null assignment check for non-null foreign key fields
- -------------------------------------------------------------
- In older versions, assigning ``None`` to a non-nullable ``ForeignKey`` or
- ``OneToOneField`` raised ``ValueError('Cannot assign None: "model.field" does
- not allow null values.')``. For consistency with other model fields which don't
- have a similar check, this check is removed.
- Removed weak password hashers from the default ``PASSWORD_HASHERS`` setting
- ---------------------------------------------------------------------------
- Django 0.90 stored passwords as unsalted MD5. Django 0.91 added support for
- salted SHA1 with automatic upgrade of passwords when a user logs in. Django 1.4
- added PBKDF2 as the default password hasher.
- If you have an old Django project with MD5 or SHA1 (even salted) encoded
- passwords, be aware that these can be cracked fairly easily with today's
- hardware. To make Django users acknowledge continued use of weak hashers, the
- following hashers are removed from the default :setting:`PASSWORD_HASHERS`
- setting::
- 'django.contrib.auth.hashers.SHA1PasswordHasher'
- 'django.contrib.auth.hashers.MD5PasswordHasher'
- 'django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher'
- 'django.contrib.auth.hashers.UnsaltedMD5PasswordHasher'
- 'django.contrib.auth.hashers.CryptPasswordHasher'
- Consider using a :ref:`wrapped password hasher <wrapping-password-hashers>` to
- strengthen the hashes in your database. If that's not feasible, add the
- :setting:`PASSWORD_HASHERS` setting to your project and add back any hashers
- that you need.
- You can check if your database has any of the removed hashers like this::
- from django.contrib.auth import get_user_model
- User = get_user_model()
- # Unsalted MD5/SHA1:
- User.objects.filter(password__startswith='md5$$')
- User.objects.filter(password__startswith='sha1$$')
- # Salted MD5/SHA1:
- User.objects.filter(password__startswith='md5$').exclude(password__startswith='md5$$')
- User.objects.filter(password__startswith='sha1$').exclude(password__startswith='sha1$$')
- # Crypt hasher:
- User.objects.filter(password__startswith='crypt$$')
- from django.db.models import CharField
- from django.db.models.functions import Length
- CharField.register_lookup(Length)
- # Unsalted MD5 passwords might not have an 'md5$$' prefix:
- User.objects.filter(password__length=32)
- :mod:`django.contrib.gis`
- -------------------------
- * Support for SpatiaLite < 3.0 and GEOS < 3.3 is dropped.
- * The ``add_postgis_srs()`` backwards compatibility alias for
- ``django.contrib.gis.utils.add_srs_entry()`` is removed.
- * On Oracle/GIS, the :class:`~django.contrib.gis.db.models.functions.Area`
- aggregate function now returns a ``float`` instead of ``decimal.Decimal``.
- (It's still wrapped in a measure of square meters.)
- * The default :class:`~django.contrib.gis.geos.GEOSGeometry` representation (WKT
- output) is trimmed by default. That is, instead of
- ``POINT (23.0000000000000000 5.5000000000000000)``, you'll get
- ``POINT (23 5.5)``.
- Miscellaneous
- -------------
- * The ``repr()`` of a ``QuerySet`` is wrapped in ``<QuerySet >`` to
- disambiguate it from a plain list when debugging.
- * ``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/'``.
- * 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.
- * The default error views now raise ``TemplateDoesNotExist`` if a nonexistent
- ``template_name`` is specified.
- * The unused ``choices`` keyword argument of the ``Select`` and
- ``SelectMultiple`` widgets' ``render()`` method is removed. The ``choices``
- argument of the ``render_options()`` method is also removed, making
- ``selected_choices`` the first argument.
- * Tests that violate deferrable database constraints will now error when run on
- a database that supports deferrable constraints.
- * Built-in management commands now use indexing of keys in ``options``, e.g.
- ``options['verbosity']``, instead of ``options.get()`` and no longer perform
- any type coercion. This could be a problem if you're calling commands using
- ``Command.execute()`` (which bypasses the argument parser that sets a default
- value) instead of :func:`~django.core.management.call_command`. Instead of
- calling ``Command.execute()``, pass the command object as the first argument
- to ``call_command()``.
- * :class:`~django.contrib.auth.backends.ModelBackend` and
- :class:`~django.contrib.auth.backends.RemoteUserBackend` now reject inactive
- users. This means that inactive users can't login and will be logged
- out if they are switched from ``is_active=True`` to ``False``. If you need
- the previous behavior, use the new
- :class:`~django.contrib.auth.backends.AllowAllUsersModelBackend` or
- :class:`~django.contrib.auth.backends.AllowAllUsersRemoteUserBackend`
- in :setting:`AUTHENTICATION_BACKENDS` instead.
- * In light of the previous change, the test client's
- :meth:`~django.test.Client.login()` method no longer always rejects inactive
- users but instead delegates this decision to the authentication backend.
- * :func:`django.views.i18n.set_language` may now return a 204 status code for
- AJAX requests.
- * The ``base_field`` attribute of
- :class:`~django.contrib.postgres.fields.RangeField` is now a type of field,
- not an instance of a field. If you have created a custom subclass of
- :class:`~django.contrib.postgres.fields.RangeField`, you should change the
- ``base_field`` attribute.
- * Middleware classes are now initialized when the server starts rather than
- during the first request.
- * If you override ``is_authenticated()`` or ``is_anonymous()`` in a custom user
- model, you must convert them to attributes or properties as described in
- :ref:`the deprecation note <user-is-auth-anon-deprecation>`.
- * When using :attr:`ModelAdmin.save_as=True
- <django.contrib.admin.ModelAdmin.save_as>`, the "Save as new" button now
- redirects to the change view for the new object instead of to the model's
- changelist. If you need the previous behavior, set the new
- :attr:`ModelAdmin.save_as_continue
- <django.contrib.admin.ModelAdmin.save_as_continue>` attribute to ``False``.
- * Required form fields now have the ``required`` HTML attribute. Set the
- :attr:`Form.use_required_attribute <django.forms.Form.use_required_attribute>`
- attribute to ``False`` to disable it. You could also add the ``novalidate``
- attribute to ``<form>`` if you don't want browser validation.
- .. _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.
- Non-timezone-aware :class:`~django.core.files.storage.Storage` API
- ------------------------------------------------------------------
- The old, non-timezone-aware methods ``accessed_time()``, ``created_time()``,
- and ``modified_time()`` are deprecated in favor of the new ``get_*_time()``
- methods.
- Third-party storage backends should implement the new methods and mark the old
- ones as deprecated. Until then, the new ``get_*_time()`` methods on the base
- :class:`~django.core.files.storage.Storage` class convert ``datetime``\s from
- the old methods as required and emit a deprecation warning as they do so.
- Third-party storage backends may retain the old methods as long as they
- wish to support earlier versions of Django.
- :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.
- * The ``django.contrib.gis.utils.precision_wkt()`` function is deprecated in
- favor of :class:`~django.contrib.gis.geos.WKTWriter`.
- ``CommaSeparatedIntegerField`` model field
- ------------------------------------------
- ``CommaSeparatedIntegerField`` is deprecated in favor of
- :class:`~django.db.models.CharField` with the
- :func:`~django.core.validators.validate_comma_separated_integer_list`
- validator::
- from django.core.validators import validate_comma_separated_integer_list
- from django.db import models
- class MyModel(models.Model):
- numbers = models.CharField(..., validators=[validate_comma_separated_integer_list])
- If you're using Oracle, ``CharField`` uses a different database field type
- (``NVARCHAR2``) than ``CommaSeparatedIntegerField`` (``VARCHAR2``). Depending
- on your database settings, this might imply a different encoding, and thus a
- different length (in bytes) for the same contents. If your stored values are
- longer than the 4000 byte limit of ``NVARCHAR2``, you should use ``TextField``
- (``NCLOB``) instead. In this case, if you have any queries that group by the
- field (e.g. annotating the model with an aggregation or using ``distinct()``)
- you'll need to change them (to defer the field).
- Using a model name as a query lookup when ``default_related_name`` is set
- -------------------------------------------------------------------------
- Assume the following models::
- from django.db import models
- class Foo(models.Model):
- pass
- class Bar(models.Model):
- foo = models.ForeignKey(Foo)
- class Meta:
- default_related_name = 'bars'
- In older versions, :attr:`~django.db.models.Options.default_related_name`
- couldn't be used as a query lookup. This is fixed and support for the old
- lookup name is deprecated. For example, since ``default_related_name`` is set
- in model ``Bar``, instead of using the model name ``bar`` as the lookup::
- >>> bar = Bar.objects.get(pk=1)
- >>> Foo.objects.get(bar=bar)
- use the default_related_name ``bars``::
- >>> Foo.objects.get(bars=bar)
- .. _search-lookup-replacement:
- ``__search`` query lookup
- -------------------------
- The ``search`` lookup, which supports MySQL only and is extremely limited in
- features, is deprecated. Replace it with a custom lookup::
- from django.db import models
- class Search(models.Lookup):
- lookup_name = 'search'
- def as_mysql(self, compiler, connection):
- lhs, lhs_params = self.process_lhs(compiler, connection)
- rhs, rhs_params = self.process_rhs(compiler, connection)
- params = lhs_params + rhs_params
- return 'MATCH (%s) AGAINST (%s IN BOOLEAN MODE)' % (lhs, rhs), params
- models.CharField.register_lookup(Search)
- models.TextField.register_lookup(Search)
- .. _user-is-auth-anon-deprecation:
- Using ``User.is_authenticated()`` and ``User.is_anonymous()`` as methods
- ------------------------------------------------------------------------
- The ``is_authenticated()`` and ``is_anonymous()`` methods of
- :class:`~django.contrib.auth.models.AbstractBaseUser` and
- :class:`~django.contrib.auth.models.AnonymousUser` classes are now
- properties. They will still work as methods until Django 2.0, but all usage
- in Django now uses attribute access.
- For example, if you use
- :class:`~django.contrib.auth.middleware.AuthenticationMiddleware` and want
- to know whether the user is currently logged-in you would use::
- if request.user.is_authenticated:
- ... # Do something for logged-in users.
- else:
- ... # Do something for anonymous users.
- instead of ``request.user.is_authenticated()``.
- This change avoids accidental information leakage if you forget to call the
- method, e.g.::
- if request.user.is_authenticated:
- return sensitive_information
- If you override these methods in a custom user model, you must change them to
- properties or attributes.
- Custom manager classes available through ``prefetch_related`` must define a ``_apply_rel_filters()`` method
- -----------------------------------------------------------------------------------------------------------
- If you defined a custom manager class available through
- :meth:`~django.db.models.query.QuerySet.prefetch_related` you must make sure
- it defines a ``_apply_rel_filters()`` method.
- This method must accept a :class:`~django.db.models.query.QuerySet` instance
- as its single argument and return a filtered version of the queryset for the
- model instance the manager is bound to.
- Miscellaneous
- -------------
- * The ``makemigrations --exit`` option is deprecated in favor of the
- :option:`makemigrations --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`.
- * The template ``Context.has_key()`` method is deprecated in favor of ``in``.
- * The private attribute ``virtual_fields`` of ``Model._meta`` is
- deprecated in favor of ``private_fields``.
- * The private keyword arguments ``virtual_only`` in
- ``Field.contribute_to_class()`` and ``virtual`` in
- ``Model._meta.add_field()`` are deprecated in favor of ``private_only``
- and ``private``, respectively.
- * The ``javascript_catalog()`` and ``json_catalog()`` views are deprecated in
- favor of class-based views :class:`~django.views.i18n.JavaScriptCatalog`
- and :class:`~django.views.i18n.JSONCatalog`.
- .. _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.urls.reverse` URLs using a dotted Python path
- is removed.
- * The ability to use a dotted Python path for the ``LOGIN_URL`` and
- ``LOGIN_REDIRECT_URL`` settings 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``.
|