23.21 What still warns: the deprecations and the releases that end them
Every deprecation in the code at this commit: what warns with RemovedInDjango2029Warning or RemovedInDjango2028Warning, the line that raises the warning, and what the code will do in Django 2029 or Django 2028, the releases that end them.
The deprecation timeline, docs/, lists under each coming release what it will remove or change. At this commit each entry but the one for select_related(True), which fails already, is code that keeps the old use working beside the new, and comments naming the warning class mark lines that must change when a deprecation ends, often with the code that will replace them.
Removed in Django 2029
What 6.2 deprecated, but for the readings of django.VERSION, warns with RemovedInDjango2029Warning, a PendingDeprecationWarning. What changed in handlers, requests, URLs and views tells the first two; What changed in querysets, What changed in expressions, lookups and the compiler and What changed in forms and validators one each.
| deprecated | warns at | in Django 2029 |
|---|---|---|
MiddlewareMixin imported from django |
warns at __getattr__ django/ |
in Django 2029 the old path fails; the class is in django |
JsonResponse given safe at all, true or false |
warns at Json django/ |
in Django 2029 the parameter goes, with the TypeError for data not a dict |
Query after Query with no chunk size; it takes 2,000 |
warns at Query django/ |
in Django 2029 ValueError, as Query raises already |
an Extract or Trunc with no tzinfo deconstructed, as a migration writes it, while USE_TZ is true |
warns at Timezone django/ |
in Django 2029 the current time zone is written into the arguments |
Email, overridden, or called from code that Django did not call |
warns at Email django/Email django/ |
in Django 2029 removed; Email alone checks the domain |
Removed in Django 2028
What 6.0 and 6.1 deprecated, and the readings of django.VERSION deprecated in 6.2, ends in Django 2028, and what of it warns does so with RemovedInDjango2028Warning, a DeprecationWarning.
Settings
What changed in settings, startup and the commands tells how the settings object warns for a deprecated setting and refuses the email settings beside MAILERS, and What changed the transitional settings.
| deprecated | warns at | in Django 2028 |
|---|---|---|
the email settings of DEPRECATED_, EMAIL_BACKEND among them, set, or read first from outside Django |
warns at Settings django/Lazy django/ |
in Django 2028 removed; Mailers reads MAILERS alone |
no MAILERS and no email setting set, when the default mailer is built |
warns at warn_ django/ |
in Django 2028 no default mailer: the global settings define MAILERS as empty (global_ django/conf/) |
USE_ set |
warns at Settings django/ |
in Django 2028 removed, with get_; a blank choice’s label is BLANK_ |
SIGNED_ set |
warns at Settings django/ |
in Django 2028 removed; _unsign_cookie tries only the salt of _cookie_ |
URLIZE_ set |
warns at no warning; read where urlize warns (Urlizer django/ |
in Django 2028 removed; "https" the default |
What changed in mail and tasks tells the changes these serve: Python’s modern email API, keyword arguments and MAILERS.
| deprecated | warns at | in Django 2028 |
|---|---|---|
fail_silently or a later argument of send_mail, send_mass_mail, mail_admins, mail_managers or django, or any after the first four of EmailMessage and Email, given by position |
warns at deprecate_ django/ |
in Django 2028 TypeError: the decorator goes, the parameters stay keyword-only |
django, called from outside Django |
warns at get_connection django/ |
in Django 2028 removed; a backend comes from mailers |
the connection, fail_silently, auth_user and auth_password arguments of the sending functions, EmailMessage’s connection and Email, fail_silently of Email |
warns at send_mail django/Email django/Email django/Email django/ |
in Django 2028 removed; a message goes through the mailer that using names, or the default |
the SMTP EmailBackend made outside mailers |
warns at Email django/ |
in Django 2028 unsupported, the timeline says |
Base, outside mailers, given a keyword it does not take, or fail_silently; fail_silently read on a backend that sets none |
warns at Base django/Base django/ |
in Django 2028 TypeError for an unknown keyword, the warning says; no fail_silently |
Admin given email_backend |
warns at Admin django/ |
in Django 2028 removed; the handler’s using names the mailer |
ADMINS or MANAGERS as (name, address) pairs, when mail is sent to them |
warns at _send_ django/ |
in Django 2028 the branch goes, and the check after it raises Improperly |
an email attached, by Email or the attachments argument |
warns at Email django/ |
in Django 2028 removed; an attachment is an email or a tuple |
BadHeaderError, SafeMIMEText and Safe taken from django.core.mail |
warns at __getattr__ django/ |
in Django 2028 removed; BadHeaderError is already ValueError |
forbid_ or sanitize_address called |
warns at forbid_ django/sanitize_address django/ |
in Django 2028 removed |
Models, querysets and SQL
Told in What changed in querysets (select_related, values_list, from_db), What changed in expressions, lookups and the compiler (the alias, the JSON lookup, the compiler), What changed in models and fields (the placeholder), What changed in forms and validators (the blank choice), What changed in the database backends and migrations (the savepoint) and What changed in the test framework (the test database).
| deprecated | warns at | in Django 2028 |
|---|---|---|
Query with no arguments, called from outside Django |
warns at Query django/ |
in Django 2028 TypeError |
select_, which fails with AttributeError |
warns at no warning; Query django/ |
in Django 2028 TypeError |
Query with flat=True and no field, which takes the first concrete field |
warns at Query django/ |
in Django 2028 TypeError |
a model’s own Model.from_db that takes no fetch_mode, called without the queryset’s mode |
warns at _get_from_db django/ |
in Django 2028 from_db always given fetch_mode |
| a percent sign in an alias | warns at Query django/ |
in Django 2028 ValueError: FORBIDDEN_ takes in the sign |
None as an exact lookup’s value on a whole JSONField, taken as JSON null |
warns at JSONExact django/ |
in Django 2028 "IS NULL"; JSON null is JSONNull |
| a field class that defines a method get_placeholder and no get_placeholder_sql, given one that calls it | warns at Field django/ |
in Django 2028 the shim goes |
SQLCompiler |
warns at SQLCompiler django/ |
in Django 2028 removed; SQLCompiler |
BLANK_ |
warns at no warning; read when USE_ is true (get_ django/ |
in Django 2028 removed |
django |
warns at savepoint django/ |
in Django 2028 removed; savepoint_create |
Base given serialize; the message names a serialize_test_db that the tree does not define |
warns at Base django/ |
in Django 2028 the parameter goes |
Templates, signing, pagination and the version
What changed in templates tells the first two; What changed in security: Content Security Policy and signing the algorithm; What changed in caching, files, signals, serialization and pagination the orphans; Django’s version: VersionTuple and get_version the readings of django.VERSION.
| deprecated | warns at | in Django 2028 |
|---|---|---|
urlize and urlizetrunc linking a web address that has no scheme, while URLIZE_ is false |
warns at Urlizer django/ |
in Django 2028 "https://" assumed |
two dots in a row in a variable tag, {{ port..name }} |
warns at Parser.parse django/ |
in Django 2028 Template, by the comment at the warning |
salted_hmac or base64_hmac with no algorithm, which takes "sha1" |
warns at salted_hmac django/base64_hmac django/ |
in Django 2028 "sha256" the default |
a Paginator or AsyncPaginator whose orphans are not fewer than its page size |
warns at Base django/ |
in Django 2028 ValueError |
django.VERSION indexed from its third component, iterated, measured, or compared with three or more components |
warns at Version django/ |
in Django 2028 four components, (year, patch, status, iteration) |
The admin
What changed in the admin tells these changes.
| deprecated | warns at | in Django 2028 |
|---|---|---|
Model set to True in a subclass |
warns at Model django/ |
in Django 2028 ValueError |
Model returning True |
warns at Model django/ |
in Django 2028 ValueError |
Model overridden without action_location, which gives the change form no actions |
warns at Model django/ |
in Django 2028 called with action_location, say the comments at its callers |
Model overridden without action_location |
warns at Model django/ |
in Django 2028 the same |
an Action unpacked or indexed like the tuple it replaced |
warns at Action.__iter__ django/Action django/ |
in Django 2028 removed |
The PostgreSQL aggregates
What changed in the other contrib apps tells them.
| deprecated | warns at | in Django 2028 |
|---|---|---|
StringAgg of django, and its delimiter given as a string |
warns at String django/ |
in Django 2028 removed; in django a string delimiter is a field reference |
BitAnd, BitOr and BitXor of the same module |
warns at BitAnd.__init__ django/BitOr.__init__ django/BitXor.__init__ django/ |
in Django 2028 removed; those of django.db.models |
Orderable subclassed |
warns at Orderable django/ |
in Django 2028 removed; Aggregate |
Which line a warning names, and what -Wd shows
A warning names one line of the stack, and Python’s filters judge it by that line’s module. Each site chooses the line: skip_file_prefixes=django_file_prefixes() names the first frame outside Django’s directory; warn_about_external_use names the code that used the feature, and is silent when that code is in the django package; warn_about_implementation names the line where an override is defined; a stack level names the frame that many levels up, and none the warning’s own line. Deprecation: warnings named by year, warn_about_external_use and deprecate_posargs tells the helpers and the filters.
Python’s default filters show a DeprecationWarning only when it names a line of __main__, and never a PendingDeprecationWarning, so a project’s modules show neither; -Wd shows each warning once for each line it names. A module of the harbour project runs old habits:
# habits.py, called from main.py run plainly and with -Wd: each habit, its warning, the line named
python main.py
nothing printed
python -Wd main.py
from django.utils.deprecation import MiddlewareMixin RemovedInDjango2029Warning the habit's line
from django.core.mail import BadHeaderError RemovedInDjango2028Warning django/core/mail/__init__.py, in __getattr__
Ship.objects.select_related() RemovedInDjango2028Warning the habit's line
Ship.objects.values_list(flat=True) RemovedInDjango2028Warning django/db/models/query.py, in QuerySet.values_list
Paginator(range(10), 2, orphans=2) RemovedInDjango2028Warning the habit's line
urlize("harbour.example.com") RemovedInDjango2028Warning django/utils/html.py, in Urlizer.__call__
Three name Django’s line: the __getattr__ of django.core.mail and values_list give no stack level, and the urlizer’s stacklevel=2 reaches only Urlizer.__call__. The development server keeps the option: its autoreloader passes its -W options to the serving process.