NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #537 most downloaded on PyPI
A high-level Python web framework that encourages rapid development and clean, pragmatic design.
Last release 24 days ago
02 Sep 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 54 of the last 60 stable releases
2 versions withdrawn
withdrawn after publishing
16 years old
442 releases · first in 2010
CVE-2022-41323: Potential denial-of-service vulnerability in internationalized URLs
October 4, 2022
Django 4.1.2 fixes a security issue with severity "medium" and several bugs in 4.1.1.
Internationalized URLs were subject to potential denial of service attack via the locale parameter.
Fixed a regression in Django 4.1 that caused a migration crash on PostgreSQL when adding a model with ExclusionConstraint (33982).
Fixed a regression in Django 4.1 that caused aggregation over a queryset that contained an Exists annotation to crash due to too many selected columns (33992).
Fixed a bug in Django 4.1 that caused an incorrect validation of CheckConstraint on NULL values (33996).
Fixed a regression in Django 4.1 that caused a QuerySet.values()/values_list() crash on ArrayAgg() and JSONBAgg() (34016).
Fixed a bug in Django 4.1 that caused .ModelAdmin.autocomplete_fields to be incorrectly selected after adding/changing related instances via popups (34025).
Fixed a regression in Django 4.1 where the app registry was not populated when running parallel tests with the multiprocessing start method spawn (34010).
Fixed a regression in Django 4.1 where the --debug-mode argument to test did not work when running parallel tests with the multiprocessing start method spawn (34010).
Fixed a regression in Django 4.1 that didn't alter a sequence type when altering type of pre-Django 4.1 serial columns on PostgreSQL (34058).
Fixed a regression in Django 4.1 that caused a crash for View subclasses with asynchronous handlers when handling non-allowed HTTP methods (34062).
Reverted caching related managers for ForeignKey, ManyToManyField, and GenericRelation that caused the incorrect refreshing of related objects (33984).
Relaxed the system check added in Django 4.1 for the same name used for multiple template tag modules to a warning (32987).
One column per quarter.
Django 4.1.1 fixes several bugs in 4.1.
September 5, 2022
Django 4.1.1 fixes several bugs in 4.1.
Reallowed, following a regression in Django 4.1, using GeoIP2() when GEOS is not installed (33886).
Fixed a regression in Django 4.1 that caused a crash of admin's autocomplete widgets when translations are deactivated (33888).
Fixed a regression in Django 4.1 that caused a crash of the test management command when running in parallel and multiprocessing start method is spawn (33891).
Fixed a regression in Django 4.1 that caused an incorrect redirection to the admin changelist view when using "Save and continue editing" and "Save and add another" options (33893).
Fixed a regression in Django 4.1 that caused a crash of ~django.db.models.expressions.Window expressions with ~django.contrib.postgres.aggregates.ArrayAgg (33898).
Fixed a regression in Django 4.1 that caused a migration crash on SQLite 3.35.5+ when removing an indexed field (33899).
Fixed a bug in Django 4.1 that caused a crash of model validation on UniqueConstraint() with field names in expressions (33902).
Fixed a bug in Django 4.1 that caused an incorrect validation of CheckConstraint() with range fields on PostgreSQL (33905).
Fixed a regression in Django 4.1 that caused an incorrect migration when adding AutoField, BigAutoField, or SmallAutoField on PostgreSQL (33919).
Fixed a regression in Django 4.1 that caused a migration crash on PostgreSQL when altering AutoField, BigAutoField, or SmallAutoField to OneToOneField (33932).
Fixed a migration crash on ManyToManyField fields with through referencing models in different apps (33938).
Fixed a regression in Django 4.1 that caused an incorrect migration when renaming a model with ManyToManyField and db_table (33953).
Reallowed, following a regression in Django 4.1, creating reverse foreign key managers on unsaved instances (33952).
Fixed a regression in Django 4.1 that caused a migration crash on SQLite < 3.20 (33960).
Fixed a regression in Django 4.1 that caused an admin crash when the ~django.contrib.admindocs app was used (33955, 33971).
- Django 4.1.13 release notes - Django 4.1.12 release notes - Django 4.1.11 release notes - Django 4.1.10 release notes - Django 4.1.9 release notes -
Django 4.1.13 release notes
Django 4.1.12 release notes
Django 4.1.11 release notes
Django 4.1.10 release notes
Django 4.1.9 release notes
Django 4.1.8 release notes
Django 4.1.7 release notes
Django 4.1.6 release notes
Django 4.1.5 release notes
Django 4.1.4 release notes
Django 4.1.3 release notes
Django 4.1.2 release notes
Django 4.1.1 release notes
Django 4.1 release notes
August 3, 2022
Welcome to Django 4.1!
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 4.0 or earlier. We've begun the deprecation process for some features.
See the /howto/upgrade-version guide if you're updating an existing project.
Django 4.1 supports Python 3.8, 3.9, 3.10, and 3.11 (as of 4.1.3). We highly recommend and only officially support the latest release of each series.
View subclasses may now define async HTTP method handlers:
import asyncio
from django.http import HttpResponse
from django.views import View
class AsyncView(View):
async def get(self, request, *args, **kwargs):
# Perform view logic using await.
await asyncio.sleep(1)
return HttpResponse("Hello async world!")
See async-class-based-views for more details.
QuerySet now provides an asynchronous interface for all data access operations. These are named as-per the existing synchronous operations but with an a prefix, for example acreate(), aget(), and so on.
The new interface allows you to write asynchronous code without needing to wrap ORM operations in sync_to_async():
async for author in Author.objects.filter(name__startswith="A"):
book = await author.books.afirst()
Note that, at this stage, the underlying database operations remain synchronous, with contributions ongoing to push asynchronous support down into the SQL compiler, and integrate asynchronous database drivers. The new asynchronous queryset interface currently encapsulates the necessary sync_to_async() operations for you, and will allow your code to take advantage of developments in the ORM's asynchronous support as it evolves.
See async-queries for details and limitations.
Check, unique, and exclusion constraints defined in the Meta.constraints option are now checked during model validation.
In order to aid users with screen readers, and other assistive technology, new <div> based form templates are available from this release. These provide more accessible navigation than the older templates, and are able to correctly group related controls, such as radio-lists, into fieldsets.
The new templates are recommended, and will become the default form rendering style when outputting a form, like {{ form }} in a template, from Django 5.0.
In order to ease adopting the new output style, the default form and formset templates are now configurable at the project level via the FORM_RENDERER setting.
See the Forms section (below) for full details.
The new CSRF_COOKIE_MASKED transitional setting allows specifying whether to mask the CSRF cookie.
~django.middleware.csrf.CsrfViewMiddleware no longer masks the CSRF cookie like it does the CSRF token in the DOM. If you are upgrading multiple instances of the same project to Django 4.1, you should set CSRF_COOKIE_MASKED to True during the transition, in order to allow compatibility with the older versions of Django. Once the transition to 4.1 is complete you can stop overriding CSRF_COOKIE_MASKED.
This setting is deprecated as of this release and will be removed in Django 5.0.
The admin dark mode CSS variables are now applied in a separate stylesheet and template block.
modeladmin-list-filters providing custom FieldListFilter subclasses can now control the query string value separator when filtering for multiple values using the __in lookup.
The admin history view is now paginated.
Related widget wrappers now have a link to object's change form.
The .AdminSite.get_app_list method now allows changing the order of apps and models on the admin index page.
The default iteration count for the PBKDF2 password hasher is increased from 320,000 to 390,000.
The .RemoteUserBackend.configure_user method now allows synchronizing user attributes with attributes in a remote system such as an LDAP directory.
The new .GEOSGeometry.make_valid method allows converting invalid geometries to valid ones.
The new clone argument for .GEOSGeometry.normalize allows creating a normalized clone of the geometry.
The new BitXor() aggregate function returns an int of the bitwise XOR of all non-null input values.
~django.contrib.postgres.indexes.SpGistIndex now supports covering indexes on PostgreSQL 14+.
~django.contrib.postgres.constraints.ExclusionConstraint now supports covering exclusion constraints using SP-GiST indexes on PostgreSQL 14+.
The new default_bounds attribute of DateTimeRangeField and DecimalRangeField allows specifying bounds for list and tuple inputs.
~django.contrib.postgres.constraints.ExclusionConstraint now allows specifying operator classes with the OpClass() expression.
The default sitemap index template <sitemapindex> now includes the <lastmod> timestamp where available, through the new ~django.contrib.sitemaps.Sitemap.get_latest_lastmod method. Custom sitemap index templates should be updated for the adjusted context variables.
~django.contrib.staticfiles.storage.ManifestStaticFilesStorage now replaces paths to CSS source map references with their hashed counterparts.
Third-party database backends can now specify the minimum required version of the database using the DatabaseFeatures.minimum_database_version attribute which is a tuple (e.g. (10, 0) means "10.0"). If a minimum version is specified, backends must also implement DatabaseWrapper.get_database_version(), which returns a tuple of the current database version. The backend's DatabaseWrapper.init_connection_state() method must call super() in order for the check to run.
The default template used to render forms when cast to a string, e.g. in templates as {{ form }}, is now configurable at the project-level by setting ~django.forms.renderers.BaseRenderer.form_template_name on the class provided for FORM_RENDERER.
.Form.template_name is now a property deferring to the renderer, but may be overridden with a string value to specify the template name per-form class.
Similarly, the default template used to render formsets can be specified via the matching ~django.forms.renderers.BaseRenderer.formset_template_name renderer attribute.
The new div.html form template, referencing .Form.template_name_div attribute, and matching .Form.as_div method, render forms using HTML <div> elements.
This new output style is recommended over the existing ~.Form.as_table, ~.Form.as_p and ~.Form.as_ul styles, as the template implements <fieldset> and <legend> to group related inputs and is easier for screen reader users to navigate.
The div-based output will become the default rendering style from Django 5.0.
In order to smooth adoption of the new <div> output style, two transitional form renderer classes are available: django.forms.renderers.DjangoDivFormRenderer and django.forms.renderers.Jinja2DivFormRenderer, for the Django and Jinja2 template backends respectively.
You can apply one of these via the FORM_RENDERER setting. For example:
FORM_RENDERER = "django.forms.renderers.DjangoDivFormRenderer"
Once the <div> output style is the default, from Django 5.0, these transitional renderers will be deprecated, for removal in Django 6.0. The FORM_RENDERER declaration can be removed at that time.
If the new <div> output style is not appropriate for your project, you should define a renderer subclass specifying ~django.forms.renderers.BaseRenderer.form_template_name and ~django.forms.renderers.BaseRenderer.formset_template_name for your required style, and set FORM_RENDERER accordingly.
For example, for the <p> output style used by ~.Form.as_p, you would define a form renderer setting form_template_name to "django/forms/p.html" and formset_template_name to "django/forms/formsets/p.html".
The new ~django.forms.BoundField.legend_tag allows rendering field labels in <legend> tags via the new tag argument of ~django.forms.BoundField.label_tag.
The new edit_only argument for .modelformset_factory and .inlineformset_factory allows preventing new objects creation.
The js and css class attributes of Media now allow using hashable objects, not only path strings, as long as those objects implement the __html__() method (typically when decorated with the ~django.utils.html.html_safe decorator).
The new .BoundField.use_fieldset and .Widget.use_fieldset attributes help to identify widgets where its inputs should be grouped in a <fieldset> with a <legend>.
The formsets-error-messages argument for ~django.forms.formsets.BaseFormSet now allows customizing error messages for invalid number of forms by passing 'too_few_forms' and 'too_many_forms' keys.
~django.forms.IntegerField, ~django.forms.FloatField, and ~django.forms.DecimalField now optionally accept a step_size argument. This is used to set the step HTML attribute, and is validated on form submission.
The ~django.conf.urls.i18n.i18n_patterns function now supports languages with both scripts and regions.
makemigrations --no-input now logs default answers and reasons why migrations cannot be created.
The new makemigrations --scriptable option diverts log output and input prompts to stderr, writing only paths of generated migration files to stdout.
The new migrate --prune option allows deleting nonexistent migrations from the django_migrations table.
Python files created by startproject, startapp, optimizemigration, makemigrations, and squashmigrations are now formatted using the black command if it is present on your PATH.
The new optimizemigration command allows optimizing operations for a migration.
The new ~django.db.migrations.operations.RenameIndex operation allows renaming indexes defined in the Meta.indexes or index_together options.
The migrations autodetector now generates ~django.db.migrations.operations.RenameIndex operations instead of RemoveIndex and AddIndex, when renaming indexes defined in the Meta.indexes.
The migrations autodetector now generates ~django.db.migrations.operations.RenameIndex operations instead of AlterIndexTogether and AddIndex, when moving indexes defined in the Meta.index_together to the Meta.indexes.
The order_by argument of the ~django.db.models.expressions.Window expression now accepts string references to fields and transforms.
The new CONN_HEALTH_CHECKS setting allows enabling health checks for persistent database connections in order to reduce the number of failed requests, e.g. after database server restart.
.QuerySet.bulk_create now supports updating fields when a row insertion fails uniqueness constraints. This is supported on MariaDB, MySQL, PostgreSQL, and SQLite 3.24+.
.QuerySet.iterator now supports prefetching related objects as long as the chunk_size argument is provided. In older versions, no prefetching was done.
~django.db.models.Q objects and querysets can now be combined using ^ as the exclusive or (XOR) operator. XOR is natively supported on MariaDB and MySQL. For databases that do not support XOR, the query will be converted to an equivalent using AND, OR, and NOT.
The new Field.non_db_attrs attribute allows customizing attributes of fields that don't affect a column definition.
On PostgreSQL, AutoField, BigAutoField, and SmallAutoField are now created as identity columns rather than serial columns with sequences.
.HttpResponse.set_cookie now supports ~datetime.timedelta objects for the max_age argument.
The new SECRET_KEY_FALLBACKS setting allows providing a list of values for secret key rotation.
The SECURE_PROXY_SSL_HEADER setting now supports a comma-separated list of protocols in the header value.
The ~django.db.models.signals.pre_delete and ~django.db.models.signals.post_delete signals now dispatch the origin of the deletion.
The HTML <script> element id attribute is no longer required when wrapping the json_script template filter.
The cached template loader is now enabled in development, when DEBUG is True, and OPTIONS['loaders'] isn't specified. You may specify OPTIONS['loaders'] to override this, if necessary.
The .DiscoverRunner now supports running tests in parallel on macOS, Windows, and any other systems where the default multiprocessing start method is spawn.
A nested atomic block marked as durable in django.test.TestCase now raises a RuntimeError, the same as outside of tests.
.SimpleTestCase.assertFormError and assertFormsetError() now support passing a form/formset object directly.
The new .ResolverMatch.captured_kwargs attribute stores the captured keyword arguments, as parsed from the URL.
The new .ResolverMatch.extra_kwargs attribute stores the additional keyword arguments passed to the view function.
SimpleLazyObject now supports addition operations.
~django.utils.safestring.mark_safe now preserves lazy objects.
The new ~django.core.validators.StepValueValidator checks if a value is an integral multiple of a given step size. This new validator is used for the new step_size argument added to form fields representing numeric values.
This section describes changes that may be needed in third-party database backends.
BaseDatabaseFeatures.has_case_insensitive_like is changed from True to False to reflect the behavior of most databases.
DatabaseIntrospection.get_key_columns() is removed. Use DatabaseIntrospection.get_relations() instead.
DatabaseOperations.ignore_conflicts_suffix_sql() method is replaced by DatabaseOperations.on_conflict_suffix_sql() that accepts the fields, on_conflict, update_fields, and unique_fields arguments.
The ignore_conflicts argument of the DatabaseOperations.insert_statement() method is replaced by on_conflict that accepts django.db.models.constants.OnConflict.
DatabaseOperations._convert_field_to_tz() is replaced by DatabaseOperations._convert_sql_to_tz() that accepts the sql, params, and tzname arguments.
Several date and time methods on DatabaseOperations now take sql and params arguments instead of field_name and return 2-tuple containing some SQL and the parameters to be interpolated into that SQL. The changed methods have these new signatures:
DatabaseOperations.date_extract_sql(lookup_type, sql, params)
DatabaseOperations.datetime_extract_sql(lookup_type, sql, params, tzname)
DatabaseOperations.time_extract_sql(lookup_type, sql, params)
DatabaseOperations.date_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_trunc_sql(self, lookup_type, sql, params, tzname)
DatabaseOperations.time_trunc_sql(lookup_type, sql, params, tzname=None)
DatabaseOperations.datetime_cast_date_sql(sql, params, tzname)
DatabaseOperations.datetime_cast_time_sql(sql, params, tzname)
Support for GDAL 2.1 is removed.
Support for PostGIS 2.4 is removed.
Upstream support for PostgreSQL 10 ends in November 2022. Django 4.1 supports PostgreSQL 11 and higher.
Upstream support for MariaDB 10.2 ends in May 2022. Django 4.1 supports MariaDB 10.3 and higher.
Admin changelist searches using multiple search terms are now applied in a single call to filter(), rather than in sequential filter() calls.
For multi-valued relationships, this means that rows from the related model must match all terms rather than any term. For example, if search_fields is set to ['child__name', 'child__age'], and a user searches for 'Jamal 17', parent rows will be returned only if there is a relationship to some 17-year-old child named Jamal, rather than also returning parents who merely have a younger or older child named Jamal in addition to some other 17-year-old.
See the spanning-multi-valued-relationships topic for more discussion of this difference. In Django 4.0 and earlier, ~django.contrib.admin.ModelAdmin.get_search_results followed the second example query, but this undocumented behavior led to queries with excessive joins.
In order to unify the behavior with many-to-many relations for unsaved model instances, a reverse foreign key now raises ValueError when calling related managers for unsaved objects.
Related managers for ~django.db.models.ForeignKey, ~django.db.models.ManyToManyField, and ~django.contrib.contenttypes.fields.GenericRelation are now cached on the ~django.db.models.Model instance to which they belong. This change was reverted in Django 4.1.2.
~django.test.runner.DiscoverRunner now returns a non-zero error code for unexpected successes from tests marked with unittest.expectedFailure.
~django.middleware.csrf.CsrfViewMiddleware no longer masks the CSRF cookie like it does the CSRF token in the DOM.
~django.middleware.csrf.CsrfViewMiddleware now uses request.META['CSRF_COOKIE'] for storing the unmasked CSRF secret rather than a masked version. This is an undocumented, private API.
The .ModelAdmin.actions and ~django.contrib.admin.ModelAdmin.inlines attributes now default to an empty tuple rather than an empty list to discourage unintended mutation.
The type="text/css" attribute is no longer included in <link> tags for CSS form media.
formset:added and formset:removed JavaScript events are now pure JavaScript events and don't depend on jQuery. See admin-javascript-inline-form-events for more details on the change.
The exc_info argument of the undocumented django.utils.log.log_response() function is replaced by exception.
The size argument of the undocumented django.views.static.was_modified_since() function is removed.
The admin log out UI now uses POST requests.
The undocumented InlineAdminFormSet.non_form_errors property is replaced by the non_form_errors() method. This is consistent with BaseFormSet.
As per above, the cached template loader is now enabled in development. You may specify OPTIONS['loaders'] to override this, if necessary.
The undocumented django.contrib.auth.views.SuccessURLAllowedHostsMixin mixin is replaced by RedirectURLMixin.
~django.db.models.BaseConstraint subclasses must implement ~django.db.models.BaseConstraint.validate method to allow those constraints to be used for validation.
The undocumented URLResolver._is_callback(), URLResolver._callback_strs, and URLPattern.lookup_str() are moved to django.contrib.admindocs.utils.
The .Model.full_clean method now converts an exclude value to a set. It’s also preferable to pass an exclude value as a set to the .Model.clean_fields, .Model.full_clean, .Model.validate_unique, and .Model.validate_constraints methods.
The minimum supported version of asgiref is increased from 3.4.1 to 3.5.2.
Combined expressions no longer use the error-prone behavior of guessing output_field when argument types match. As a consequence, resolving an output_field for database functions and combined expressions may now crash with mixed types. You will need to explicitly set the output_field in such cases.
The makemessages command no longer changes .po files when up to date. In older versions, POT-Creation-Date was always updated.
Logging out via GET requests to the built-in logout view is deprecated. Use POST requests instead.
If you want to retain the user experience of an HTML link, you can use a form that is styled to appear as a link:
<form id="logout-form" method="post" action="{% url 'admin:logout' %}">
{% csrf_token %}
<button type="submit">{% translate "Log out" %}</button>
</form>
#logout-form {
display: inline;
}
#logout-form button {
background: none;
border: none;
cursor: pointer;
padding: 0;
text-decoration: underline;
}
The context for sitemap index templates of a flat list of URLs is deprecated. Custom sitemap index templates should be updated for the adjusted context variables, expecting a list of objects with location and optional lastmod attributes.
CSRF_COOKIE_MASKED transitional setting is deprecated.
The name argument of django.utils.functional.cached_property is deprecated as it's unnecessary as of Python 3.6.
The opclasses argument of django.contrib.postgres.constraints.ExclusionConstraint is deprecated in favor of using OpClass() in .ExclusionConstraint.expressions. To use it, you need to add 'django.contrib.postgres' in your INSTALLED_APPS.
After making this change, makemigrations will generate a new migration with two operations: RemoveConstraint and AddConstraint. Since this change has no effect on the database schema, the ~django.db.migrations.operations.SeparateDatabaseAndState operation can be used to only update the migration state without running any SQL. Move the generated operations into the state_operations argument of ~django.db.migrations.operations.SeparateDatabaseAndState. For example:
class Migration(migrations.Migration):
...
operations = [
migrations.SeparateDatabaseAndState(
database_operations=[],
state_operations=[
migrations.RemoveConstraint(...),
migrations.AddConstraint(...),
],
),
]
The undocumented ability to pass errors=None to .SimpleTestCase.assertFormError and assertFormsetError() is deprecated. Use errors=[] instead.
django.contrib.sessions.serializers.PickleSerializer is deprecated due to the risk of remote code execution.
The usage of QuerySet.iterator() on a queryset that prefetches related objects without providing the chunk_size argument is deprecated. In older versions, no prefetching was done. Providing a value for chunk_size signifies that the additional query per chunk needed to prefetch is desired.
Passing unsaved model instances to related filters is deprecated. In Django 5.0, the exception will be raised.
created=True is added to the signature of .RemoteUserBackend.configure_user. Support for RemoteUserBackend subclasses that do not accept this argument is deprecated.
The django.utils.timezone.utc alias to datetime.timezone.utc is deprecated. Use datetime.timezone.utc directly.
Passing a response object and a form/formset name to SimpleTestCase.assertFormError() and assertFormsetError() is deprecated. Use:
assertFormError(response.context["form_name"], ...) assertFormsetError(response.context["formset_name"], ...)
or pass the form/formset object directly instead.
The undocumented django.contrib.gis.admin.OpenLayersWidget is deprecated.
django.contrib.auth.hashers.CryptPasswordHasher is deprecated.
The ability to pass nulls_first=False or nulls_last=False to Expression.asc() and Expression.desc() methods, and the OrderBy expression is deprecated. Use None instead.
The "django/forms/default.html" and "django/forms/formsets/default.html" templates which are a proxy to the table-based templates are deprecated. Use the specific template instead.
The undocumented LogoutView.get_next_page() method is renamed to get_success_url().
These features have reached the end of their deprecation cycle and are removed in Django 4.1.
See deprecated-features-3.2 for details on these changes, including how to remove usage of these features.
Support for assigning objects which don't support creating deep copies with copy.deepcopy() to class attributes in TestCase.setUpTestData() is removed.
Support for using a boolean value in .BaseCommand.requires_system_checks is removed.
The whitelist argument and domain_whitelist attribute of django.core.validators.EmailValidator are removed.
The default_app_config application configuration variable is removed.
TransactionTestCase.assertQuerysetEqual() no longer calls repr() on a queryset when compared to string values.
The django.core.cache.backends.memcached.MemcachedCache backend is removed.
Support for the pre-Django 3.2 format of messages used by django.contrib.messages.storage.cookie.CookieStorage is removed.
Nothing published for this version
Nothing published for this version
Nothing published for this version
CVE-2023-24580: Potential denial-of-service vulnerability in file uploads
February 14, 2023
Django 4.0.10 fixes a security issue with severity "moderate" in 4.0.9.
Passing certain inputs to multipart forms could result in too many open files or memory exhaustion, and provided a potential vector for a denial-of-service attack.
The number of files parts parsed is now limited via the new
:setting:DATA_UPLOAD_MAX_NUMBER_FILES setting.
CVE-2023-23969: Potential denial-of-service via Accept-Language headers
February 1, 2023
Django 4.0.9 fixes a security issue with severity "moderate" in 4.0.8.
Accept-Language headersThe parsed values of Accept-Language headers are cached in order to avoid
repetitive parsing. This leads to a potential denial-of-service vector via
excessive memory usage if large header values are sent.
In order to avoid this vulnerability, the Accept-Language header is now
parsed up to a maximum length.
CVE-2022-41323: Potential denial-of-service vulnerability in internationalized URLs
October 4, 2022
Django 4.0.8 fixes a security issue with severity "medium" in 4.0.7.
Internationalized URLs were subject to potential denial of service attack via the locale parameter.
CVE-2022-36359: Potential reflected file download vulnerability in FileResponse
August 3, 2022
Django 4.0.7 fixes a security issue with severity "high" in 4.0.6.
An application may have been vulnerable to a reflected file download (RFD) attack that sets the Content-Disposition header of a ~django.http.FileResponse when the filename was derived from user-supplied input. The filename is now escaped to avoid this possibility.
CVE-2022-34265: Potential SQL injection via Trunc(kind) and Extract(lookup_name) arguments
July 4, 2022
Django 4.0.6 fixes a security issue with severity "high" in 4.0.5.
Trunc() and Extract() database functions were subject to SQL injection if untrusted data was used as a kind/lookup_name value.
Applications that constrain the lookup name and kind choice to a known safe list are unaffected.
Django 4.0.5 fixes several bugs in 4.0.4.
June 1, 2022
Django 4.0.5 fixes several bugs in 4.0.4.
Fixed a bug in Django 4.0 where not all :setting:OPTIONS <CACHES-OPTIONS>
were passed to a Redis client (:ticket:33681).
Fixed a bug in Django 4.0 that caused a crash of QuerySet.filter() on
IsNull() expressions (:ticket:33705).
Fixed a bug in Django 4.0 where a hidden quick filter toolbar in the admin's
navigation sidebar was focusable (:ticket:33725).
CVE-2022-28346: Potential SQL injection in QuerySet.annotate(), aggregate(), and extra()
April 11, 2022
Django 4.0.4 fixes two security issues with severity "high" and two bugs in 4.0.3.
.QuerySet.annotate, ~.QuerySet.aggregate, and ~.QuerySet.extra methods were subject to SQL injection in column aliases, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to these methods.
.QuerySet.explain method was subject to SQL injection in option names, using a suitably crafted dictionary, with dictionary expansion, as the **options argument.
Fixed a regression in Django 4.0 that caused ignoring multiple FilteredRelation() relationships to the same field (33598).
Fixed a regression in Django 3.2.4 that caused the auto-reloader to no longer detect changes when the DIRS option of the TEMPLATES setting contained an empty string (33628).
Django 4.0.3 fixes several bugs in 4.0.2. Also, all Python code in Django is reformatted with black.
March 1, 2022
Django 4.0.3 fixes several bugs in 4.0.2. Also, all Python code in Django is reformatted with black.
Prevented, following a regression in Django 4.0.1, makemigrations from generating infinite migrations for a model with ManyToManyField to a lowercased swappable model such as 'auth.user' (33515).
Fixed a regression in Django 4.0 that caused a crash when rendering invalid inlines with ~django.contrib.admin.ModelAdmin.readonly_fields in the admin (33547).
CVE-2022-22818: Possible XSS via {% debug %} template tag
February 1, 2022
Django 4.0.2 fixes two security issues with severity "medium" and several bugs in 4.0.1. Also, the latest string translations from Transifex are incorporated, with a special mention for Bulgarian (fully translated).
The {% debug %} template tag didn't properly encode the current context, posing an XSS attack vector.
In order to avoid this vulnerability, {% debug %} no longer outputs information when the DEBUG setting is False, and it ensures all context variables are correctly escaped when the DEBUG setting is True.
Passing certain inputs to multipart forms could result in an infinite loop when parsing files.
Fixed a bug in Django 4.0 where TestCase.captureOnCommitCallbacks() could execute callbacks multiple times (33410).
Fixed a regression in Django 4.0 where help_text was HTML-escaped in automatically-generated forms (33419).
Fixed a regression in Django 4.0 that caused displaying an incorrect name for class-based views on the technical 404 debug page (33425).
Fixed a regression in Django 4.0 that caused an incorrect repr of ResolverMatch for class-based views (33426).
Fixed a regression in Django 4.0 that caused a crash of makemigrations on models without Meta.order_with_respect_to but with a field named _order (33449).
Fixed a regression in Django 4.0 that caused incorrect .ModelAdmin.radio_fields layout in the admin (33407).
Fixed a duplicate operation regression in Django 4.0 that caused a migration crash when altering a primary key type for a concrete parent model referenced by a foreign key (33462).
Fixed a bug in Django 4.0 that caused a crash of QuerySet.aggregate() after annotate() on an aggregate function with a default (33468).
Fixed a regression in Django 4.0 that caused a crash of makemigrations when renaming a field of a renamed model (33480).
CVE-2021-45115: Denial-of-service possibility in UserAttributeSimilarityValidator
January 4, 2022
Django 4.0.1 fixes one security issue with severity "medium", two security issues with severity "low", and several bugs in 4.0.
.UserAttributeSimilarityValidator incurred significant overhead evaluating submitted password that were artificially large in relative to the comparison values. On the assumption that access to user registration was unrestricted this provided a potential vector for a denial-of-service attack.
In order to mitigate this issue, relatively long values are now ignored by UserAttributeSimilarityValidator.
This issue has severity "medium" according to the Django security policy.
Due to leveraging the Django Template Language's variable resolution logic, the dictsort template filter was potentially vulnerable to information disclosure or unintended method calls, if passed a suitably crafted key.
In order to avoid this possibility, dictsort now works with a restricted resolution logic, that will not call methods, nor allow indexing on dictionaries.
As a reminder, all untrusted user input should be validated before use.
This issue has severity "low" according to the Django security policy.
Storage.save() allowed directory-traversal if directly passed suitably crafted file names.
This issue has severity "low" according to the Django security policy.
Fixed a regression in Django 4.0 that caused a crash of assertFormsetError() on a formset named form (33346).
Fixed a bug in Django 4.0 that caused a crash on booleans with the RedisCache backend (33361).
Relaxed the check added in Django 4.0 to reallow use of a duck-typed HttpRequest in django.views.decorators.cache.cache_control() and never_cache() decorators (33350).
Fixed a regression in Django 4.0 that caused creating bogus migrations for models that reference swappable models such as auth.User (33366).
Fixed a long standing bug in geos-geometry-collections and ~django.contrib.gis.geos.Polygon that caused a crash on some platforms (reported on macOS based on the ARM64 architecture) (32600).
- Django 4.0.10 release notes - Django 4.0.9 release notes - Django 4.0.8 release notes - Django 4.0.7 release notes - Django 4.0.6 release notes - Dj
Django 4.0.10 release notes
Django 4.0.9 release notes
Django 4.0.8 release notes
Django 4.0.7 release notes
Django 4.0.6 release notes
Django 4.0.5 release notes
Django 4.0.4 release notes
Django 4.0.3 release notes
Django 4.0.2 release notes
Django 4.0.1 release notes
Django 4.0 release notes
December 7, 2021
Welcome to Django 4.0!
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 3.2 or earlier. We've begun the deprecation process for some features.
See the /howto/upgrade-version guide if you're updating an existing project.
Django 4.0 supports Python 3.8, 3.9, and 3.10. We highly recommend and only officially support the latest release of each series.
The Django 3.2.x series is the last to support Python 3.6 and 3.7.
The Python standard library's zoneinfo is now the default timezone implementation in Django.
This is the next step in the migration from using pytz to using zoneinfo. Django 3.2 allowed the use of non-pytz time zones. Django 4.0 makes zoneinfo the default implementation. Support for pytz is now deprecated and will be removed in Django 5.0.
zoneinfo is part of the Python standard library from Python 3.9. The backports.zoneinfo package is automatically installed alongside Django if you are using Python 3.8.
The move to zoneinfo should be largely transparent. Selection of the current timezone, conversion of datetime instances to the current timezone in forms and templates, as well as operations on aware datetimes in UTC are unaffected.
However, if you are working with non-UTC time zones, and using the pytz normalize() and localize() APIs, possibly with the TIME_ZONE setting, you will need to audit your code, since pytz and zoneinfo are not entirely equivalent.
To give time for such an audit, the transitional USE_DEPRECATED_PYTZ setting allows continued use of pytz during the 4.x release cycle. This setting will be removed in Django 5.0.
In addition, a pytz_deprecation_shim package, created by the zoneinfo author, can be used to assist with the migration from pytz. This package provides shims to help you safely remove pytz, and has a detailed migration guide showing how to move to the new zoneinfo APIs.
Using pytz_deprecation_shim and the USE_DEPRECATED_PYTZ transitional setting is recommended if you need a gradual update path.
The new *expressions positional argument of UniqueConstraint() enables creating functional unique constraints on expressions and database functions. For example:
from django.db import models
from django.db.models import UniqueConstraint
from django.db.models.functions import Lower
class MyModel(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
class Meta:
constraints = [
UniqueConstraint(
Lower("first_name"),
Lower("last_name").desc(),
name="first_last_name_unique",
),
]
Functional unique constraints are added to models using the Meta.constraints option.
The new scrypt password hasher is more secure and recommended over PBKDF2. However, it's not the default as it requires OpenSSL 1.1+ and more memory.
The new django.core.cache.backends.redis.RedisCache cache backend provides built-in support for caching with Redis. redis-py 3.0.0 or higher is required. For more details, see the documentation on caching with Redis in Django.
Forms, Formsets, and ~django.forms.ErrorList are now rendered using the template engine to enhance customization. See the new ~django.forms.Form.render, ~django.forms.Form.get_context, and ~django.forms.Form.template_name for Form and formset rendering for Formset.
The admin/base.html template now has a new block header which contains the admin site header.
The new .ModelAdmin.get_formset_kwargs method allows customizing the keyword arguments passed to the constructor of a formset.
The navigation sidebar now has a quick filter toolbar.
The new context variable model which contains the model class for each model is added to the .AdminSite.each_context method.
The new .ModelAdmin.search_help_text attribute allows specifying a descriptive text for the search box.
The .InlineModelAdmin.verbose_name_plural attribute now fallbacks to the .InlineModelAdmin.verbose_name + 's'.
jQuery is upgraded from version 3.5.1 to 3.6.0.
The admindocs now allows esoteric setups where ROOT_URLCONF is not a string.
The model section of the admindocs now shows cached properties.
The default iteration count for the PBKDF2 password hasher is increased from 260,000 to 320,000.
The new LoginView.next_page attribute and ~django.contrib.auth.views.LoginView.get_default_redirect_url method allow customizing the redirect after login.
Added support for SpatiaLite 5.
~django.contrib.gis.gdal.GDALRaster now allows creating rasters in any GDAL virtual filesystem.
The new ~django.contrib.gis.admin.GISModelAdmin class allows customizing the widget used for GeometryField. This is encouraged instead of deprecated GeoModelAdmin and OSMGeoAdmin.
The PostgreSQL backend now supports connecting by a service name. See postgresql-connection-settings for more details.
The new ~django.contrib.postgres.operations.AddConstraintNotValid operation allows creating check constraints on PostgreSQL without verifying that all existing rows satisfy the new constraint.
The new ~django.contrib.postgres.operations.ValidateConstraint operation allows validating check constraints which were created using ~django.contrib.postgres.operations.AddConstraintNotValid on PostgreSQL.
The new ArraySubquery() expression allows using subqueries to construct lists of values on PostgreSQL.
The new trigram_word_similar lookup, and the TrigramWordDistance() and TrigramWordSimilarity() expressions allow using trigram word similarity.
~django.contrib.staticfiles.storage.ManifestStaticFilesStorage now replaces paths to JavaScript source map references with their hashed counterparts.
The new manifest_storage argument of ~django.contrib.staticfiles.storage.ManifestFilesMixin and ~django.contrib.staticfiles.storage.ManifestStaticFilesStorage allows customizing the manifest file storage.
The new async API for django.core.cache.backends.base.BaseCache begins the process of making cache backends async-compatible. The new async methods all have a prefixed names, e.g. aadd(), aget(), aset(), aget_or_set(), or adelete_many().
Going forward, the a prefix will be used for async variants of methods generally.
CSRF protection now consults the Origin header, if present. To facilitate this, some changes to the CSRF_TRUSTED_ORIGINS setting are required.
~django.forms.ModelChoiceField now includes the provided value in the params argument of a raised ~django.core.exceptions.ValidationError for the invalid_choice error message. This allows custom error messages to use the %(value)s placeholder.
~django.forms.formsets.BaseFormSet now renders non-form errors with an additional class of nonform to help distinguish them from form-specific errors.
~django.forms.formsets.BaseFormSet now allows customizing the widget used when deleting forms via ~django.forms.formsets.BaseFormSet.can_delete by setting the ~django.forms.formsets.BaseFormSet.deletion_widget attribute or overriding ~django.forms.formsets.BaseFormSet.get_deletion_widget method.
Added support and translations for the Malay language.
~django.views.generic.edit.DeleteView now uses ~django.views.generic.edit.FormMixin, allowing you to provide a ~django.forms.Form subclass, with a checkbox for example, to confirm deletion. In addition, this allows DeleteView to function with django.contrib.messages.views.SuccessMessageMixin.
In accordance with FormMixin, object deletion for POST requests is handled in form_valid(). Custom delete logic in delete() handlers should be moved to form_valid(), or a shared helper method, as needed.
The alias of the database used in an SQL call is now passed as extra context along with each message to the django-db-logger logger.
The runserver management command now supports the --skip-checks option.
On PostgreSQL, dbshell now supports specifying a password file.
The shell command now respects sys.__interactivehook__ at startup. This allows loading shell history between interactive sessions. As a consequence, readline is no longer loaded if running in isolated mode.
The new BaseCommand.suppressed_base_arguments attribute allows suppressing unsupported default command options in the help output.
The new startapp --exclude and startproject --exclude options allow excluding directories from the template.
New QuerySet.contains(obj) method returns whether the queryset contains the given object. This tries to perform the query in the simplest and fastest way possible.
The new precision argument of the Round() database function allows specifying the number of decimal places after rounding.
.QuerySet.bulk_create now sets the primary key on objects when using SQLite 3.35+.
~django.db.models.DurationField now supports multiplying and dividing by scalar values on SQLite.
.QuerySet.bulk_update now returns the number of objects updated.
The new .Expression.empty_result_set_value attribute allows specifying a value to return when the function is used over an empty result set.
The skip_locked argument of .QuerySet.select_for_update is now allowed on MariaDB 10.6+.
~django.db.models.Lookup expressions may now be used in QuerySet annotations, aggregations, and directly in filters.
The new default argument for built-in aggregates allows specifying a value to be returned when the queryset (or grouping) contains no entries, rather than None.
The ~django.middleware.security.SecurityMiddleware now adds the Cross-Origin Opener Policy header with a value of 'same-origin' to prevent cross-origin popups from sharing the same browsing context. You can prevent this header from being added by setting the SECURE_CROSS_ORIGIN_OPENER_POLICY setting to None.
The new stdout argument for ~django.db.models.signals.pre_migrate and ~django.db.models.signals.post_migrate signals allows redirecting output to a stream-like object. It should be preferred over sys.stdout and print when emitting verbose output in order to allow proper capture when testing.
floatformat template filter now allows using the u suffix to force disabling localization.
The new serialized_aliases argument of django.test.utils.setup_databases determines which DATABASES aliases test databases should have their state serialized to allow usage of the serialized_rollback feature.
The test --buffer option now supports parallel tests.
The new logger argument to ~django.test.runner.DiscoverRunner allows a Python logger to be used for logging.
The new .DiscoverRunner.log method provides a way to log messages that uses the DiscoverRunner.logger, or prints to the console if not set.
~django.test.runner.DiscoverRunner can now execute tests in a random order using the test --shuffle option.
The test --parallel option now supports the value auto to run one test process for each processor core.
.TestCase.captureOnCommitCallbacks now captures new callbacks added while executing .transaction.on_commit callbacks.
This section describes changes that may be needed in third-party database backends.
DatabaseOperations.year_lookup_bounds_for_date_field() and year_lookup_bounds_for_datetime_field() methods now take the optional iso_year argument in order to support bounds for ISO-8601 week-numbering years.
The second argument of DatabaseSchemaEditor._unique_sql() and _create_unique_sql() methods is now fields instead of columns.
Support for PostGIS 2.3 is removed.
Support for GDAL 2.0 and GEOS 3.5 is removed.
Upstream support for PostgreSQL 9.6 ends in November 2021. Django 4.0 supports PostgreSQL 10 and higher.
Also, the minimum supported version of psycopg2 is increased from 2.5.4 to 2.8.4, as psycopg2 2.8.4 is the first release to support Python 3.8.
Upstream support for Oracle 12.2 ends in March 2022 and for Oracle 18c it ends in June 2021. Django 3.2 will be supported until April 2024. Django 4.0 officially supports Oracle 19c.
Values in the CSRF_TRUSTED_ORIGINS setting must include the scheme (e.g. 'http://' or 'https://') instead of only the hostname.
Also, values that started with a dot, must now also include an asterisk before the dot. For example, change '.example.com' to 'https://*.example.com'.
A system check detects any required changes.
As CSRF protection now consults the Origin header, you may need to set CSRF_TRUSTED_ORIGINS, particularly if you allow requests from subdomains by setting CSRF_COOKIE_DOMAIN (or SESSION_COOKIE_DOMAIN if CSRF_USE_SESSIONS is enabled) to a value starting with a dot.
The ~django.middleware.security.SecurityMiddleware no longer sets the X-XSS-Protection header if the SECURE_BROWSER_XSS_FILTER setting is True. The setting is removed.
Most modern browsers don't honor the X-XSS-Protection HTTP header. You can use Content-Security-Policy without allowing 'unsafe-inline' scripts instead.
If you want to support legacy browsers and set the header, use this line in a custom middleware:
response.headers.setdefault("X-XSS-Protection", "1; mode=block")
The migrations autodetector now uses model states instead of model classes. Also, migration operations for ForeignKey and ManyToManyField fields no longer specify attributes which were not passed to the fields during initialization.
As a side-effect, running makemigrations might generate no-op AlterField operations for ManyToManyField and ForeignKey fields in some cases.
~django.views.generic.edit.DeleteView now uses ~django.views.generic.edit.FormMixin to handle POST requests. As a consequence, any custom deletion logic in delete() handlers should be moved to form_valid(), or a shared helper method, if required.
Django 4.0 inadvertently changed the table and column naming scheme on Oracle. This causes errors for models and fields with names longer than 30 characters. Unfortunately, renaming some Oracle tables and columns is required. Use the upgrade script in 33789 to generate RENAME statements to change naming scheme.
Support for cx_Oracle < 7.0 is removed.
To allow serving a Django site on a subpath without changing the value of STATIC_URL, the leading slash is removed from that setting (now 'static/') in the default startproject template.
The ~django.contrib.admin.AdminSite method for the admin index view is no longer decorated with never_cache when accessed directly, rather than via the recommended AdminSite.urls property, or AdminSite.get_urls() method.
Unsupported operations on a sliced queryset now raise TypeError instead of AssertionError.
The undocumented django.test.runner.reorder_suite() function is renamed to reorder_tests(). It now accepts an iterable of tests rather than a test suite, and returns an iterator of tests.
Calling FileSystemStorage.delete() with an empty name now raises ValueError instead of AssertionError.
Calling EmailMultiAlternatives.attach_alternative() or EmailMessage.attach() with an invalid content or mimetype arguments now raise ValueError instead of AssertionError.
~django.test.SimpleTestCase.assertHTMLEqual no longer considers a non-boolean attribute without a value equal to an attribute with the same name and value.
Tests that fail to load, for example due to syntax errors, now always match when using test --tag.
The undocumented django.contrib.admin.utils.lookup_needs_distinct() function is renamed to lookup_spawns_duplicates().
The undocumented HttpRequest.get_raw_uri() method is removed. The .HttpRequest.build_absolute_uri method may be a suitable alternative.
The object argument of undocumented ModelAdmin.log_addition(), log_change(), and log_deletion() methods is renamed to obj.
~django.utils.feedgenerator.RssFeed, ~django.utils.feedgenerator.Atom1Feed, and their subclasses now emit elements with no content as self-closing tags.
NodeList.render() no longer casts the output of render() method for individual nodes to a string. Node.render() should always return a string as documented.
The where_class property of django.db.models.sql.query.Query and the where_class argument to the private get_extra_restriction() method of ForeignObject and ForeignObjectRel are removed. If needed, initialize django.db.models.sql.where.WhereNode instead.
The filter_clause argument of the undocumented Query.add_filter() method is replaced by two positional arguments filter_lhs and filter_rhs.
~django.middleware.csrf.CsrfViewMiddleware now uses request.META['CSRF_COOKIE_NEEDS_UPDATE'] in place of request.META['CSRF_COOKIE_USED'], request.csrf_cookie_needs_reset, and response.csrf_cookie_set to track whether the CSRF cookie should be sent. This is an undocumented, private API.
The undocumented TRANSLATOR_COMMENT_MARK constant is moved from django.template.base to django.utils.translation.template.
The real_apps argument of the undocumented django.db.migrations.state.ProjectState.__init__() method must now be a set if provided.
~django.forms.RadioSelect and ~django.forms.CheckboxSelectMultiple widgets are now rendered in <div> tags so they are announced more concisely by screen readers. If you need the previous behavior, override the widget template with the appropriate template from Django 3.2.
The floatformat template filter no longer depends on the USE_L10N setting and always returns localized output. Use the u suffix to disable localization.
The default value of the USE_L10N setting is changed to True. See the Localization section above for more details.
As part of the move to zoneinfo, django.utils.timezone.utc is changed to alias datetime.timezone.utc.
The minimum supported version of asgiref is increased from 3.3.2 to 3.4.1.
As part of the move to zoneinfo, use of pytz time zones is deprecated.
Accordingly, the is_dst arguments to the following are also deprecated:
django.db.models.query.QuerySet.datetimes
django.db.models.functions.Trunc
django.db.models.functions.TruncSecond
django.db.models.functions.TruncMinute
django.db.models.functions.TruncHour
django.db.models.functions.TruncDay
django.db.models.functions.TruncWeek
django.db.models.functions.TruncMonth
django.db.models.functions.TruncQuarter
django.db.models.functions.TruncYear
django.utils.timezone.make_aware
Support for use of pytz will be removed in Django 5.0.
In order to follow good practice, the default value of the USE_TZ setting will change from False to True, and time zone support will be enabled by default, in Django 5.0.
Note that the default settings.py file created by django-admin startproject includes USE_TZ = True since Django 1.4.
You can set USE_TZ to False in your project settings before then to opt-out.
In order to follow good practice, the default value of the USE_L10N setting is changed from False to True.
Moreover USE_L10N is deprecated as of this release. Starting with Django 5.0, by default, any date or number displayed by Django will be localized.
The {% localize %} tag and the localize/ unlocalize filters will still be honored by Django.
SERIALIZE test setting is deprecated as it can be inferred from the ~django.test.TestCase.databases with the serialized_rollback option enabled.
The undocumented django.utils.baseconv module is deprecated.
The undocumented django.utils.datetime_safe module is deprecated.
The default sitemap protocol for sitemaps built outside the context of a request will change from 'http' to 'https' in Django 5.0.
The extra_tests argument for .DiscoverRunner.build_suite and .DiscoverRunner.run_tests is deprecated.
The ~django.contrib.postgres.aggregates.ArrayAgg, ~django.contrib.postgres.aggregates.JSONBAgg, and ~django.contrib.postgres.aggregates.StringAgg aggregates will return None when there are no rows instead of [], [], and '' respectively in Django 5.0. If you need the previous behavior, explicitly set default to Value([]), Value('[]'), or Value('').
The django.contrib.gis.admin.GeoModelAdmin and OSMGeoAdmin classes are deprecated. Use ~django.contrib.admin.ModelAdmin and ~django.contrib.gis.admin.GISModelAdmin instead.
Since form rendering now uses the template engine, the undocumented BaseForm._html_output() helper method is deprecated.
The ability to return a str from ErrorList and ErrorDict is deprecated. It is expected these methods return a SafeString.
These features have reached the end of their deprecation cycle and are removed in Django 4.0.
See deprecated-features-3.0 for details on these changes, including how to remove usage of these features.
django.utils.http.urlquote(), urlquote_plus(), urlunquote(), and urlunquote_plus() are removed.
django.utils.encoding.force_text() and smart_text() are removed.
django.utils.translation.ugettext(), ugettext_lazy(), ugettext_noop(), ungettext(), and ungettext_lazy() are removed.
django.views.i18n.set_language() doesn't set the user language in request.session (key _language).
alias=None is required in the signature of django.db.models.Expression.get_group_by_cols() subclasses.
django.utils.text.unescape_entities() is removed.
django.utils.http.is_safe_url() is removed.
See deprecated-features-3.1 for details on these changes, including how to remove usage of these features.
The PASSWORD_RESET_TIMEOUT_DAYS setting is removed.
The isnull lookup no longer allows using non-boolean values as the right-hand side.
The django.db.models.query_utils.InvalidQuery exception class is removed.
The django-admin.py entry point is removed.
The HttpRequest.is_ajax() method is removed.
Support for the pre-Django 3.1 encoding format of cookies values used by django.contrib.messages.storage.cookie.CookieStorage is removed.
Support for the pre-Django 3.1 password reset tokens in the admin site (that use the SHA-1 hashing algorithm) is removed.
Support for the pre-Django 3.1 encoding format of sessions is removed.
Support for the pre-Django 3.1 django.core.signing.Signer signatures (encoded with the SHA-1 algorithm) is removed.
Support for the pre-Django 3.1 django.core.signing.dumps() signatures (encoded with the SHA-1 algorithm) in django.core.signing.loads() is removed.
Support for the pre-Django 3.1 user sessions (that use the SHA-1 algorithm) is removed.
The get_response argument for django.utils.deprecation.MiddlewareMixin.__init__() is required and doesn't accept None.
The providing_args argument for django.dispatch.Signal is removed.
The length argument for django.utils.crypto.get_random_string() is required.
The list message for ModelMultipleChoiceField is removed.
Support for passing raw column aliases to QuerySet.order_by() is removed.
The NullBooleanField model field is removed, except for support in historical migrations.
django.conf.urls.url() is removed.
The django.contrib.postgres.fields.JSONField model field is removed, except for support in historical migrations.
django.contrib.postgres.fields.jsonb.KeyTransform and django.contrib.postgres.fields.jsonb.KeyTextTransform are removed.
django.contrib.postgres.forms.JSONField is removed.
The {% ifequal %} and {% ifnotequal %} template tags are removed.
The DEFAULT_HASHING_ALGORITHM transitional setting is removed.
Nothing published for this version
Nothing published for this version
Nothing published for this version
CVE-2024-27351: Potential regular expression denial-of-service in django.utils.text.Truncator.words()
March 4, 2024
Django 3.2.25 fixes a security issue with severity "moderate" and a regression in 3.2.24.
django.utils.text.Truncator.words()django.utils.text.Truncator.words() method (with html=True) and
:tfilter:truncatewords_html template filter were subject to a potential
regular expression denial-of-service attack using a suitably crafted string
(follow up to :cve:2019-14232 and :cve:2023-43665).
intcomma template filter could
return a leading comma for string representation of floats (:ticket:35172).CVE-2024-24680: Potential denial-of-service in intcomma template filter
February 6, 2024
Django 3.2.24 fixes a security issue with severity "moderate" in 3.2.23.
intcomma template filterThe intcomma template filter was subject to a potential denial-of-service
attack when used with very long strings.
CVE-2023-46695: Potential denial of service vulnerability in UsernameField on Windows
November 1, 2023
Django 3.2.23 fixes a security issue with severity "moderate" in 3.2.22.
The NFKC normalization is slow on Windows. As a consequence, django.contrib.auth.forms.UsernameField was subject to a potential denial of service attack via certain inputs with a very large number of Unicode characters.
In order to avoid the vulnerability, invalid values longer than UsernameField.max_length are no longer normalized, since they cannot pass validation anyway.
CVE-2023-43665: Denial-of-service possibility in django.utils.text.Truncator
October 4, 2023
Django 3.2.22 fixes a security issue with severity "moderate" in 3.2.21.
django.utils.text.TruncatorFollowing the fix for :cve:2019-14232, the regular expressions used in the
implementation of django.utils.text.Truncator's chars() and words()
methods (with html=True) were revised and improved. However, these regular
expressions still exhibited linear backtracking complexity, so when given a
very long, potentially malformed HTML input, the evaluation would still be
slow, leading to a potential denial of service vulnerability.
The chars() and words() methods are used to implement the
:tfilter:truncatechars_html and :tfilter:truncatewords_html template
filters, which were thus also vulnerable.
The input processed by Truncator, when operating in HTML mode, has been
limited to the first five million characters in order to avoid potential
performance and memory issues.
CVE-2023-41164: Potential denial of service vulnerability in django.utils.encoding.uri_to_iri()
September 4, 2023
Django 3.2.21 fixes a security issue with severity "moderate" in 3.2.20.
django.utils.encoding.uri_to_iri()django.utils.encoding.uri_to_iri() was subject to potential denial of
service attack via certain inputs with a very large number of Unicode
characters.
CVE-2023-36053: Potential regular expression denial of service vulnerability in EmailValidator/URLValidator
July 3, 2023
Django 3.2.20 fixes a security issue with severity "moderate" in 3.2.19.
EmailValidator/URLValidatorEmailValidator and URLValidator were subject to potential regular
expression denial of service attack via a very large number of domain name
labels of emails and URLs.
CVE-2023-31047: Potential bypass of validation when uploading multiple files using one form field
May 3, 2023
Django 3.2.19 fixes a security issue with severity "low" in 3.2.18.
Uploading multiple files using one form field has never been supported by .forms.FileField or .forms.ImageField as only the last uploaded file was validated. Unfortunately, uploading_multiple_files topic suggested otherwise.
In order to avoid the vulnerability, ~django.forms.ClearableFileInput and ~django.forms.FileInput form widgets now raise ValueError when the multiple HTML attribute is set on them. To prevent the exception and keep the old behavior, set allow_multiple_selected to True.
For more details on using the new attribute and handling of multiple files through a single field, see uploading_multiple_files.
CVE-2023-24580: Potential denial-of-service vulnerability in file uploads
February 14, 2023
Django 3.2.18 fixes a security issue with severity "moderate" in 3.2.17.
Passing certain inputs to multipart forms could result in too many open files or memory exhaustion, and provided a potential vector for a denial-of-service attack.
The number of files parts parsed is now limited via the new
:setting:DATA_UPLOAD_MAX_NUMBER_FILES setting.
CVE-2023-23969: Potential denial-of-service via Accept-Language headers
February 1, 2023
Django 3.2.17 fixes a security issue with severity "moderate" in 3.2.16.
Accept-Language headersThe parsed values of Accept-Language headers are cached in order to avoid
repetitive parsing. This leads to a potential denial-of-service vector via
excessive memory usage if large header values are sent.
In order to avoid this vulnerability, the Accept-Language header is now
parsed up to a maximum length.
CVE-2022-41323: Potential denial-of-service vulnerability in internationalized URLs
October 4, 2022
Django 3.2.16 fixes a security issue with severity "medium" in 3.2.15.
Internationalized URLs were subject to potential denial of service attack via the locale parameter.
CVE-2022-36359: Potential reflected file download vulnerability in FileResponse
August 3, 2022
Django 3.2.15 fixes a security issue with severity "high" in 3.2.14.
An application may have been vulnerable to a reflected file download (RFD) attack that sets the Content-Disposition header of a ~django.http.FileResponse when the filename was derived from user-supplied input. The filename is now escaped to avoid this possibility.
CVE-2022-34265: Potential SQL injection via Trunc(kind) and Extract(lookup_name) arguments
July 4, 2022
Django 3.2.14 fixes a security issue with severity "high" in 3.2.13.
Trunc() and Extract() database functions were subject to SQL injection if untrusted data was used as a kind/lookup_name value.
Applications that constrain the lookup name and kind choice to a known safe list are unaffected.
CVE-2022-28346: Potential SQL injection in QuerySet.annotate(), aggregate(), and extra()
April 11, 2022
Django 3.2.13 fixes two security issues with severity "high" in 3.2.12 and a regression in 3.2.4.
.QuerySet.annotate, ~.QuerySet.aggregate, and ~.QuerySet.extra methods were subject to SQL injection in column aliases, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to these methods.
.QuerySet.explain method was subject to SQL injection in option names, using a suitably crafted dictionary, with dictionary expansion, as the **options argument.
Fixed a regression in Django 3.2.4 that caused the auto-reloader to no longer detect changes when the DIRS option of the TEMPLATES setting contained an empty string (33628).
CVE-2022-22818: Possible XSS via {% debug %} template tag
February 1, 2022
Django 3.2.12 fixes two security issues with severity "medium" in 3.2.11.
{% debug %} template tagThe {% debug %} template tag didn't properly encode the current context,
posing an XSS attack vector.
In order to avoid this vulnerability, {% debug %} no longer outputs
information when the DEBUG setting is False, and it ensures all context
variables are correctly escaped when the DEBUG setting is True.
Passing certain inputs to multipart forms could result in an infinite loop when parsing files.
CVE-2021-45115: Denial-of-service possibility in UserAttributeSimilarityValidator
January 4, 2022
Django 3.2.11 fixes one security issue with severity "medium" and two security issues with severity "low" in 3.2.10.
.UserAttributeSimilarityValidator incurred significant overhead evaluating submitted password that were artificially large in relative to the comparison values. On the assumption that access to user registration was unrestricted this provided a potential vector for a denial-of-service attack.
In order to mitigate this issue, relatively long values are now ignored by UserAttributeSimilarityValidator.
This issue has severity "medium" according to the Django security policy.
Due to leveraging the Django Template Language's variable resolution logic, the dictsort template filter was potentially vulnerable to information disclosure or unintended method calls, if passed a suitably crafted key.
In order to avoid this possibility, dictsort now works with a restricted resolution logic, that will not call methods, nor allow indexing on dictionaries.
As a reminder, all untrusted user input should be validated before use.
This issue has severity "low" according to the Django security policy.
Storage.save() allowed directory-traversal if directly passed suitably crafted file names.
This issue has severity "low" according to the Django security policy.
CVE-2021-44420: Potential bypass of an upstream access control based on URL paths
December 7, 2021
Django 3.2.10 fixes a security issue with severity "low" and a bug in 3.2.9.
HTTP requests for URLs with trailing newlines could bypass an upstream access control based on URL paths.
setUpTestData()
with BinaryField on PostgreSQL, which is memoryview-backed
(:ticket:33333).Django 3.2.9 fixes a bug in 3.2.8 and adds compatibility with Python 3.10.
November 1, 2021
Django 3.2.9 fixes a bug in 3.2.8 and adds compatibility with Python 3.10.
33194).Django 3.2.8 fixes two bugs in 3.2.7.
October 5, 2021
Django 3.2.8 fixes two bugs in 3.2.7.
Fixed a bug in Django 3.2 that caused incorrect links on read-only fields in
the admin (:ticket:33077).
Fixed a regression in Django 3.2 that caused incorrect selection of items
across all pages when actions were placed both on the top and bottom of the
admin change-list view (:ticket:33083).
Django 3.2.7 fixes a bug in 3.2.6.
September 1, 2021
Django 3.2.7 fixes a bug in 3.2.6.
32992).Django 3.2.6 fixes several bugs in 3.2.5.
August 2, 2021
Django 3.2.6 fixes several bugs in 3.2.5.
Fixed a regression in Django 3.2 that caused a crash validating "NaN"
input with a forms.DecimalField when additional constraints, e.g.
max_value, were specified (:ticket:32949).
Fixed a bug in Django 3.2 where a system check would crash on a model with a
reverse many-to-many relation inherited from a parent class
(:ticket:32947).
CVE-2021-35042: Potential SQL injection via unsanitized QuerySet.order_by() input
July 1, 2021
Django 3.2.5 fixes a security issue with severity "high" and several bugs in 3.2.4. Also, the latest string translations from Transifex are incorporated.
QuerySet.order_by() inputUnsanitized user input passed to QuerySet.order_by() could bypass intended
column reference validation in path marked for deprecation resulting in a
potential SQL injection even if a deprecation warning is emitted.
As a mitigation the strict column reference validation was restored for the
duration of the deprecation period. This regression appeared in 3.1 as a side
effect of fixing :ticket:31426.
The issue is not present in the main branch as the deprecated path has been removed.
Fixed a regression in Django 3.2 that caused a crash of
QuerySet.values_list(…, named=True) after prefetch_related()
(:ticket:32812).
Fixed a bug in Django 3.2 that caused a migration crash on MySQL 8.0.13+ when
altering BinaryField, JSONField, or TextField to non-nullable
(:ticket:32503).
Fixed a regression in Django 3.2 that caused a migration crash on MySQL
8.0.13+ when adding nullable BinaryField, JSONField, or TextField
with a default value (:ticket:32832).
Fixed a bug in Django 3.2 where a system check would crash on a model with an
invalid app_label (:ticket:32863).
CVE-2021-33203: Potential directory traversal via admindocs
June 2, 2021
Django 3.2.4 fixes two security issues and several bugs in 3.2.3.
Staff members could use the ~django.contrib.admindocs TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by the developers to also expose the file contents, then not only the existence but also the file contents would have been exposed.
As a mitigation, path sanitation is now applied and only files within the template root directories can be loaded.
~django.core.validators.URLValidator, ~django.core.validators.validate_ipv4_address, and ~django.core.validators.validate_ipv46_address didn't prohibit leading zeros in octal literals. If you used such values you could suffer from indeterminate SSRF, RFI, and LFI attacks.
~django.core.validators.validate_ipv4_address and ~django.core.validators.validate_ipv46_address validators were not affected on Python 3.9.5+.
Fixed a bug in Django 3.2 where a final catch-all view in the admin didn't respect the server-provided value of SCRIPT_NAME when redirecting unauthenticated users to the login page (32754).
Fixed a bug in Django 3.2 where a system check would crash on an abstract model (32733).
Prevented unnecessary initialization of unused caches following a regression in Django 3.2 (32747).
Fixed a crash in Django 3.2 that could occur when running mod_wsgi with the recommended settings while the Windows colorama library was installed (32740).
Fixed a bug in Django 3.2 that would trigger the auto-reloader for template changes when directory paths were specified with strings (32744).
Fixed a regression in Django 3.2 that caused a crash of auto-reloader with AttributeError, e.g. inside a Conda environment (32783).
Fixed a regression in Django 3.2 that caused a loss of precision for operations with DecimalField on MySQL (32793).
Django 3.2.3 fixes several bugs in 3.2.2.
May 13, 2021
Django 3.2.3 fixes several bugs in 3.2.2.
Prepared for mysqlclient > 2.0.3 support (32732).
Fixed a regression in Django 3.2 that caused the incorrect filtering of querysets combined with the | operator (32717).
Fixed a regression in Django 3.2.1 where saving FileField would raise a SuspiciousFileOperation even when a custom ~django.db.models.FileField.upload_to returns a valid file path (32718).
CVE-2021-32052: Header injection possibility since URLValidator accepted newlines in input on Python 3.9.5+
May 6, 2021
Django 3.2.2 fixes a security issue and a bug in 3.2.1.
On Python 3.9.5+, ~django.core.validators.URLValidator didn't prohibit newlines and tabs. If you used values with newlines in HTTP response, you could suffer from header injection attacks. Django itself wasn't vulnerable because ~django.http.HttpResponse prohibits newlines in HTTP headers.
Moreover, the URLField form field which uses URLValidator silently removes newlines and tabs on Python 3.9.5+, so the possibility of newlines entering your data only existed if you are using this validator outside of the form fields.
This issue was introduced by the 43882 fix.
Prevented, following a regression in Django 3.2.1, makemigrations from generating infinite migrations for a model with Meta.ordering contained OrderBy expressions (32714).
CVE-2021-31542: Potential directory-traversal via uploaded files
May 4, 2021
Django 3.2.1 fixes a security issue and several bugs in 3.2.
MultiPartParser, UploadedFile, and FieldFile allowed directory-traversal via uploaded files with suitably crafted file names.
In order to mitigate this risk, stricter basename and path sanitation is now applied.
Corrected detection of GDAL 3.2 on Windows (32544).
Fixed a bug in Django 3.2 where subclasses of BigAutoField and SmallAutoField were not allowed for the DEFAULT_AUTO_FIELD setting (32620).
Fixed a regression in Django 3.2 that caused a crash of QuerySet.values()/values_list() after QuerySet.union(), intersection(), and difference() when it was ordered by an unannotated field (32627).
Restored, following a regression in Django 3.2, displaying an exception message on the technical 404 debug page (32637).
Fixed a bug in Django 3.2 where a system check would crash on a reverse one-to-one relationships in CheckConstraint.check or UniqueConstraint.condition (32635).
Fixed a regression in Django 3.2 that caused a crash of .ModelAdmin.search_fields when searching against phrases with unbalanced quotes (32649).
Fixed a bug in Django 3.2 where variable lookup errors were logged rendering the sitemap template if alternates were not defined (32648).
Fixed a regression in Django 3.2 that caused a crash when combining Q() objects which contains boolean expressions (32548).
Fixed a regression in Django 3.2 that caused a crash of QuerySet.update() on a queryset ordered by inherited or joined fields on MySQL and MariaDB (32645).
Fixed a regression in Django 3.2 that caused a crash when decoding a cookie value, used by django.contrib.messages.storage.cookie.CookieStorage, in the pre-Django 3.2 format (32643).
Fixed a regression in Django 3.2 that stopped the shift-key modifier selecting multiple rows in the admin changelist (32647).
Fixed a bug in Django 3.2 where a system check would crash on the STATICFILES_DIRS setting with a list of 2-tuples of (prefix, path) (32665).
Fixed a long standing bug involving queryset bitwise combination when used with subqueries that began manifesting in Django 3.2, due to a separate fix using Exists to exclude() multi-valued relationships (32650).
Fixed a bug in Django 3.2 where variable lookup errors were logged when rendering some admin templates (32681).
Fixed a bug in Django 3.2 where an admin changelist would crash when deleting objects filtered against multi-valued relationships (32682). The admin changelist now uses Exists() instead of QuerySet.distinct() because calling delete() after distinct() is not allowed in Django 3.2 to address a data loss possibility.
Fixed a regression in Django 3.2 where the calling process environment would not be passed to the dbshell command on PostgreSQL (32687).
Fixed a performance regression in Django 3.2 when building complex filters with subqueries (32632). As a side-effect the private API to check django.db.sql.query.Query equality is removed.
- Django 3.2.25 release notes - Django 3.2.24 release notes - Django 3.2.23 release notes - Django 3.2.22 release notes - Django 3.2.21 release notes
Django 3.2.25 release notes
Django 3.2.24 release notes
Django 3.2.23 release notes
Django 3.2.22 release notes
Django 3.2.21 release notes
Django 3.2.20 release notes
Django 3.2.19 release notes
Django 3.2.18 release notes
Django 3.2.17 release notes
Django 3.2.16 release notes
Django 3.2.15 release notes
Django 3.2.14 release notes
Django 3.2.13 release notes
Django 3.2.12 release notes
Django 3.2.11 release notes
Django 3.2.10 release notes
Django 3.2.9 release notes
Django 3.2.8 release notes
Django 3.2.7 release notes
Django 3.2.6 release notes
Django 3.2.5 release notes
Django 3.2.4 release notes
Django 3.2.3 release notes
Django 3.2.2 release notes
Django 3.2.1 release notes
Django 3.2 release notes
April 6, 2021
Welcome to Django 3.2!
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 3.1 or earlier. We've begun the deprecation process for some features.
See the /howto/upgrade-version guide if you're updating an existing project.
Django 3.2 is designated as a long-term support release. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 2.2, will end in April 2022.
Django 3.2 supports Python 3.6, 3.7, 3.8, 3.9, and 3.10 (as of 3.2.9). We highly recommend and only officially support the latest release of each series.
Most pluggable applications define an ~django.apps.AppConfig subclass in an apps.py submodule. Many define a default_app_config variable pointing to this class in their __init__.py.
When the apps.py submodule exists and defines a single ~django.apps.AppConfig subclass, Django now uses that configuration automatically, so you can remove default_app_config.
default_app_config made it possible to declare only the application's path in INSTALLED_APPS (e.g. 'django.contrib.admin') rather than the app config's path (e.g. 'django.contrib.admin.apps.AdminConfig'). It was introduced for backwards-compatibility with the former style, with the intent to switch the ecosystem to the latter, but the switch didn't happen.
With automatic AppConfig discovery, default_app_config is no longer needed. As a consequence, it's deprecated.
See configuring-applications-ref for full details.
When defining a model, if no field in a model is defined with primary_key=True an implicit primary key is added. The type of this implicit primary key can now be controlled via the DEFAULT_AUTO_FIELD setting and AppConfig.default_auto_field attribute. No more needing to override primary keys in all models.
Maintaining the historical behavior, the default value for DEFAULT_AUTO_FIELD is ~django.db.models.AutoField. Starting with 3.2 new projects are generated with DEFAULT_AUTO_FIELD set to ~django.db.models.BigAutoField. Also, new apps are generated with AppConfig.default_auto_field set to ~django.db.models.BigAutoField. In a future Django release the default value of DEFAULT_AUTO_FIELD will be changed to ~django.db.models.BigAutoField.
To avoid unwanted migrations in the future, either explicitly set DEFAULT_AUTO_FIELD to ~django.db.models.AutoField:
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
or configure it on a per-app basis:
from django.apps import AppConfig
class MyAppConfig(AppConfig):
default_auto_field = "django.db.models.AutoField"
name = "my_app"
or on a per-model basis:
from django.db import models
class MyModel(models.Model):
id = models.AutoField(primary_key=True)
In anticipation of the changing default, a system check will provide a warning if you do not have an explicit setting for DEFAULT_AUTO_FIELD.
When changing the value of DEFAULT_AUTO_FIELD, migrations for the primary key of existing auto-created through tables cannot be generated currently. See the DEFAULT_AUTO_FIELD docs for details on migrating such tables.
The new *expressions positional argument of Index() enables creating functional indexes on expressions and database functions. For example:
from django.db import models
from django.db.models import F, Index, Value
from django.db.models.functions import Lower, Upper
class MyModel(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
height = models.IntegerField()
weight = models.IntegerField()
class Meta:
indexes = [
Index(
Lower("first_name"),
Upper("last_name").desc(),
name="first_last_name_idx",
),
Index(
F("height") / (F("weight") + Value(5)),
name="calc_idx",
),
]
Functional indexes are added to models using the Meta.indexes option.
The new django.core.cache.backends.memcached.PyMemcacheCache cache backend allows using the pymemcache library for memcached. pymemcache 3.4.0 or higher is required. For more details, see the documentation on caching in Django.
The new ~django.contrib.admin.display decorator allows for easily adding options to custom display functions that can be used with ~django.contrib.admin.ModelAdmin.list_display or ~django.contrib.admin.ModelAdmin.readonly_fields.
Likewise, the new ~django.contrib.admin.action decorator allows for easily adding options to action functions that can be used with ~django.contrib.admin.ModelAdmin.actions.
Using the @display decorator has the advantage that it is now possible to use the @property decorator when needing to specify attributes on the custom method. Prior to this it was necessary to use the property() function instead after assigning the required attributes to the method.
Using decorators has the advantage that these options are more discoverable as they can be suggested by completion utilities in code editors. They are merely a convenience and still set the same attributes on the functions under the hood.
.ModelAdmin.search_fields now allows searching against quoted phrases with spaces.
Read-only related fields are now rendered as navigable links if target models are registered in the admin.
The admin now supports theming, and includes a dark theme that is enabled according to browser settings. See admin-theming for more details.
.ModelAdmin.autocomplete_fields now respects ForeignKey.to_field and ForeignKey.limit_choices_to when searching a related model.
The admin now installs a final catch-all view that redirects unauthenticated users to the login page, regardless of whether the URL is otherwise valid. This protects against a potential model enumeration privacy issue.
Although not recommended, you may set the new .AdminSite.final_catch_all_view to False to disable the catch-all view.
The default iteration count for the PBKDF2 password hasher is increased from 216,000 to 260,000.
The default variant for the Argon2 password hasher is changed to Argon2id. memory_cost and parallelism are increased to 102,400 and 8 respectively to match the argon2-cffi defaults.
Increasing the memory_cost pushes the required memory from 512 KB to 100 MB. This is still rather conservative but can lead to problems in memory constrained environments. If this is the case, the existing hasher can be subclassed to override the defaults.
The default salt entropy for the Argon2, MD5, PBKDF2, SHA-1 password hashers is increased from 71 to 128 bits.
The new absolute_max argument for ~django.contrib.contenttypes.forms.generic_inlineformset_factory allows customizing the maximum number of forms that can be instantiated when supplying POST data. See formsets-absolute-max for more details.
The new can_delete_extra argument for ~django.contrib.contenttypes.forms.generic_inlineformset_factory allows removal of the option to delete extra forms. See ~.BaseFormSet.can_delete_extra for more information.
The .GDALRaster.transform method now supports ~django.contrib.gis.gdal.SpatialReference.
The ~django.contrib.gis.gdal.DataSource class now supports pathlib.Path.
The ~django.contrib.gis.utils.LayerMapping class now supports pathlib.Path.
The new .ExclusionConstraint.include attribute allows creating covering exclusion constraints on PostgreSQL 12+.
The new ExclusionConstraint.opclasses attribute allows setting PostgreSQL operator classes.
The new JSONBAgg.ordering attribute determines the ordering of the aggregated elements.
The new .JSONBAgg.distinct attribute determines if aggregated values will be distinct.
The ~django.contrib.postgres.operations.CreateExtension operation now checks that the extension already exists in the database and skips the migration if so.
The new ~django.contrib.postgres.operations.CreateCollation and ~django.contrib.postgres.operations.RemoveCollation operations allow creating and dropping collations on PostgreSQL. See manage-postgresql-collations for more details.
Lookups for ~django.contrib.postgres.fields.ArrayField now allow (non-nested) arrays containing expressions as right-hand sides.
The new OpClass() expression allows creating functional indexes on expressions with a custom operator class. See new_functional_indexes for more details.
The new ~django.contrib.sitemaps.Sitemap attributes ~django.contrib.sitemaps.Sitemap.alternates, ~django.contrib.sitemaps.Sitemap.languages and ~django.contrib.sitemaps.Sitemap.x_default allow generating sitemap alternates to localized versions of your pages.
The new item_comments hook allows specifying a comments URL per feed item.
Third-party database backends can now skip or mark as expected failures tests in Django's test suite using the new DatabaseFeatures.django_test_skips and django_test_expected_failures attributes.
The new ~django.views.decorators.common.no_append_slash decorator allows individual views to be excluded from APPEND_SLASH URL normalization.
Custom ~django.views.debug.ExceptionReporter subclasses can now define the ~django.views.debug.ExceptionReporter.html_template_path and ~django.views.debug.ExceptionReporter.text_template_path properties to override the templates used to render exception reports.
The new FileUploadHandler.upload_interrupted() callback allows handling interrupted uploads.
The new absolute_max argument for .formset_factory, .inlineformset_factory, and .modelformset_factory allows customizing the maximum number of forms that can be instantiated when supplying POST data. See formsets-absolute-max for more details.
The new can_delete_extra argument for .formset_factory, .inlineformset_factory, and .modelformset_factory allows removal of the option to delete extra forms. See ~.BaseFormSet.can_delete_extra for more information.
~django.forms.formsets.BaseFormSet now reports a user facing error, rather than raising an exception, when the management form is missing or has been tampered with. To customize this error message, pass the error_messages argument with the key 'missing_management_form' when instantiating the formset.
The week_format attributes of ~django.views.generic.dates.WeekMixin and ~django.views.generic.dates.WeekArchiveView now support the '%V' ISO 8601 week format.
loaddata now supports fixtures stored in XZ archives (.xz) and LZMA archives (.lzma).
dumpdata now can compress data in the bz2, gz, lzma, or xz formats.
makemigrations can now be called without an active database connection. In that case, check for a consistent migration history is skipped.
.BaseCommand.requires_system_checks now supports specifying a list of tags. System checks registered in the chosen tags will be checked for errors prior to executing the command. In previous versions, either all or none of the system checks were performed.
Support for colored terminal output on Windows is updated. Various modern terminal environments are automatically detected, and the options for enabling support in other cases are improved. See syntax-coloring for more details.
The new Operation.migration_name_fragment property allows providing a filename fragment that will be used to name a migration containing only that operation.
Migrations now support serialization of pure and concrete path objects from pathlib, and os.PathLike instances.
The new no_key parameter for .QuerySet.select_for_update, supported on PostgreSQL, allows acquiring weaker locks that don't block the creation of rows that reference locked rows through a foreign key.
When() expression now allows using the condition argument with lookups.
The new .Index.include and .UniqueConstraint.include attributes allow creating covering indexes and covering unique constraints on PostgreSQL 11+.
The new .UniqueConstraint.opclasses attribute allows setting PostgreSQL operator classes.
The .QuerySet.update method now respects the order_by() clause on MySQL and MariaDB.
FilteredRelation() now supports nested relations.
The of argument of .QuerySet.select_for_update is now allowed on MySQL 8.0.1+.
Value() expression now automatically resolves its output_field to the appropriate Field subclass based on the type of its provided value for bool, bytes, float, int, str, datetime.date, datetime.datetime, datetime.time, datetime.timedelta, decimal.Decimal, and uuid.UUID instances. As a consequence, resolving an output_field for database functions and combined expressions may now crash with mixed types when using Value(). You will need to explicitly set the output_field in such cases.
The new .QuerySet.alias method allows creating reusable aliases for expressions that don't need to be selected but are used for filtering, ordering, or as a part of complex expressions.
The new ~django.db.models.functions.Collate function allows filtering and ordering by specified database collations.
The field_name argument of .QuerySet.in_bulk now accepts distinct fields if there's only one field specified in .QuerySet.distinct.
The new tzinfo parameter of the ~django.db.models.functions.TruncDate and ~django.db.models.functions.TruncTime database functions allows truncating datetimes in a specific timezone.
The new db_collation argument for CharField and TextField allows setting a database collation for the field.
Added the ~django.db.models.functions.Random database function.
aggregation-functions, F(), OuterRef(), and other expressions now allow using transforms. See using-transforms-in-expressions for details.
The new durable argument for ~django.db.transaction.atomic guarantees that changes made in the atomic block will be committed if the block exits without errors. A nested atomic block marked as durable will raise a RuntimeError.
Added the ~django.db.models.functions.JSONObject database function.
The new django.core.paginator.Paginator.get_elided_page_range method allows generating a page range with some of the values elided. If there are a large number of pages, this can be helpful for generating a reasonable number of page links in a template.
Response headers are now stored in .HttpResponse.headers. This can be used instead of the original dict-like interface of HttpResponse objects. Both interfaces will continue to be supported. See setting-header-fields for details.
The new headers parameter of ~django.http.HttpResponse, ~django.template.response.SimpleTemplateResponse, and ~django.template.response.TemplateResponse allows setting response ~django.http.HttpResponse.headers on instantiation.
The SECRET_KEY setting is now checked for a valid value upon first access, rather than when settings are first loaded. This enables running management commands that do not rely on the SECRET_KEY without needing to provide a value. As a consequence of this, calling ~django.conf.settings.configure without providing a valid SECRET_KEY, and then going on to access settings.SECRET_KEY will now raise an ~django.core.exceptions.ImproperlyConfigured exception.
The new Signer.sign_object() and Signer.unsign_object() methods allow signing complex data structures. See signing-complex-data for more details.
Also, signing.dumps() and ~django.core.signing.loads become shortcuts for .TimestampSigner.sign_object and ~.TimestampSigner.unsign_object.
The new JSONL serializer allows using the JSON Lines format with dumpdata and loaddata. This can be useful for populating large databases because data is loaded line by line into memory, rather than being loaded all at once.
Signal.send_robust() now logs exceptions.
floatformat template filter now allows using the g suffix to force grouping by the THOUSAND_SEPARATOR for the active locale.
Templates cached with Cached template loaders are now correctly reloaded in development.
Objects assigned to class attributes in .TestCase.setUpTestData are now isolated for each test method. Such objects are now required to support creating deep copies with copy.deepcopy. Assigning objects which don't support deepcopy() is deprecated and will be removed in Django 4.1.
~django.test.runner.DiscoverRunner now enables faulthandler by default. This can be disabled by using the test --no-faulthandler option.
~django.test.runner.DiscoverRunner and the test management command can now track timings, including database setup and total run time. This can be enabled by using the test --timing option.
~django.test.Client now preserves the request query string when following 307 and 308 redirects.
The new .TestCase.captureOnCommitCallbacks method captures callback functions passed to transaction.on_commit() in a list. This allows you to test such callbacks without using the slower .TransactionTestCase.
TransactionTestCase.assertQuerysetEqual() now supports direct comparison against another queryset rather than being restricted to comparison against a list of string representations of objects when using the default value for the transform argument.
The new depth parameter of django.utils.timesince.timesince() and django.utils.timesince.timeuntil() functions allows specifying the number of adjacent time units to return.
Built-in validators now include the provided value in the params argument of a raised ~django.core.exceptions.ValidationError. This allows custom error messages to use the %(value)s placeholder.
The .ValidationError equality operator now ignores messages and params ordering.
This section describes changes that may be needed in third-party database backends.
The new DatabaseFeatures.introspected_field_types property replaces these features:
can_introspect_autofield
can_introspect_big_integer_field
can_introspect_binary_field
can_introspect_decimal_field
can_introspect_duration_field
can_introspect_ip_address_field
can_introspect_positive_integer_field
can_introspect_small_integer_field
can_introspect_time_field
introspected_big_auto_field_type
introspected_small_auto_field_type
introspected_boolean_field_type
To enable support for covering indexes (.Index.include) and covering unique constraints (.UniqueConstraint.include), set DatabaseFeatures.supports_covering_indexes to True.
Third-party database backends must implement support for column database collations on CharFields and TextFields or set DatabaseFeatures.supports_collation_on_charfield and DatabaseFeatures.supports_collation_on_textfield to False. If non-deterministic collations are not supported, set supports_non_deterministic_collations to False.
DatabaseOperations.random_function_sql() is removed in favor of the new ~django.db.models.functions.Random database function.
DatabaseOperations.date_trunc_sql() and DatabaseOperations.time_trunc_sql() now take the optional tzname argument in order to truncate in a specific timezone.
DatabaseClient.runshell() now gets arguments and an optional dictionary with environment variables to the underlying command-line client from DatabaseClient.settings_to_cmd_args_env() method. Third-party database backends must implement DatabaseClient.settings_to_cmd_args_env() or override DatabaseClient.runshell().
Third-party database backends must implement support for functional indexes (.Index.expressions) or set DatabaseFeatures.supports_expression_indexes to False. If COLLATE is not a part of the CREATE INDEX statement, set DatabaseFeatures.collate_as_index_expression to True.
Pagination links in the admin are now 1-indexed instead of 0-indexed, i.e. the query string for the first page is ?p=1 instead of ?p=0.
The new admin catch-all view will break URL patterns routed after the admin URLs and matching the admin URL prefix. You can either adjust your URL ordering or, if necessary, set AdminSite.final_catch_all_view to False, disabling the catch-all view. See whats-new-3.2 for more details.
Minified JavaScript files are no longer included with the admin. If you require these files to be minified, consider using a third party app or external build tool. The minified vendored JavaScript files packaged with the admin (e.g. jquery.min.js) are still included.
.ModelAdmin.prepopulated_fields no longer strips English stop words, such as 'a' or 'an'.
Support for PostGIS 2.2 is removed.
The Oracle backend now clones polygons (and geometry collections containing polygons) before reorienting them and saving them to the database. They are no longer mutated in place. You might notice this if you use the polygons after a model is saved.
Upstream support for PostgreSQL 9.5 ends in February 2021. Django 3.2 supports PostgreSQL 9.6 and higher.
The end of upstream support for MySQL 5.6 is April 2021. Django 3.2 supports MySQL 5.7 and higher.
Django now supports non-pytz time zones, such as Python 3.9+'s zoneinfo module and its backport.
The undocumented SpatiaLiteOperations.proj4_version() method is renamed to proj_version().
~django.utils.text.slugify now removes leading and trailing dashes and underscores.
The intcomma and intword template filters no longer depend on the USE_L10N setting.
Support for argon2-cffi < 19.1.0 is removed.
The cache keys no longer includes the language when internationalization is disabled (USE_I18N = False) and localization is enabled (USE_L10N = True). After upgrading to Django 3.2 in such configurations, the first request to any previously cached value will be a cache miss.
ForeignKey.validate() now uses ~django.db.models.Model._base_manager rather than ~django.db.models.Model._default_manager to check that related instances exist.
When an application defines an ~django.apps.AppConfig subclass in an apps.py submodule, Django now uses this configuration automatically, even if it isn't enabled with default_app_config. Set default = False in the ~django.apps.AppConfig subclass if you need to prevent this behavior. See whats-new-3.2 for more details.
Instantiating an abstract model now raises TypeError.
Keyword arguments to ~django.test.utils.setup_databases are now keyword-only.
The undocumented django.utils.http.limited_parse_qsl() function is removed. Please use urllib.parse.parse_qsl instead.
django.test.utils.TestContextDecorator now uses ~unittest.TestCase.addCleanup so that cleanups registered in the ~unittest.TestCase.setUp method are called before TestContextDecorator.disable().
SessionMiddleware now raises a ~django.contrib.sessions.exceptions.SessionInterrupted exception instead of ~django.core.exceptions.SuspiciousOperation when a session is destroyed in a concurrent request.
The django.db.models.Field equality operator now correctly distinguishes inherited field instances across models. Additionally, the ordering of such fields is now defined.
The undocumented django.core.files.locks.lock() function now returns False if the file cannot be locked, instead of raising BlockingIOError.
The password reset mechanism now invalidates tokens when the user email is changed.
makemessages command no longer processes invalid locales specified using makemessages --locale option, when they contain hyphens ('-').
The django.contrib.auth.forms.ReadOnlyPasswordHashField form field is now ~django.forms.Field.disabled by default. Therefore UserChangeForm.clean_password() is no longer required to return the initial value.
The cache.get_many(), get_or_set(), has_key(), incr(), decr(), incr_version(), and decr_version() cache operations now correctly handle None stored in the cache, in the same way as any other value, instead of behaving as though the key didn't exist.
Due to a python-memcached limitation, the previous behavior is kept for the deprecated MemcachedCache backend.
The minimum supported version of SQLite is increased from 3.8.3 to 3.9.0.
~django.contrib.messages.storage.cookie.CookieStorage now stores messages in the 6265 compliant format. Support for cookies that use the old format remains until Django 4.1.
The minimum supported version of asgiref is increased from 3.2.10 to 3.3.2.
Assigning objects which don't support creating deep copies with copy.deepcopy to class attributes in .TestCase.setUpTestData is deprecated.
Using a boolean value in .BaseCommand.requires_system_checks is deprecated. Use '__all__' instead of True, and [] (an empty list) instead of False.
The whitelist argument and domain_whitelist attribute of ~django.core.validators.EmailValidator are deprecated. Use allowlist instead of whitelist, and domain_allowlist instead of domain_whitelist. You may need to rename whitelist in existing migrations.
The default_app_config application configuration variable is deprecated, due to the now automatic AppConfig discovery. See whats-new-3.2 for more details.
Automatically calling repr() on a queryset in TransactionTestCase.assertQuerysetEqual(), when compared to string values, is deprecated. If you need the previous behavior, explicitly set transform to repr.
The django.core.cache.backends.memcached.MemcachedCache backend is deprecated as python-memcached has some problems and seems to be unmaintained. Use django.core.cache.backends.memcached.PyMemcacheCache or django.core.cache.backends.memcached.PyLibMCCache instead.
The format of messages used by django.contrib.messages.storage.cookie.CookieStorage is different from the format generated by older versions of Django. Support for the old format remains until Django 4.1.
Nothing published for this version
Nothing published for this version
Nothing published for this version
CVE-2021-44420: Potential bypass of an upstream access control based on URL paths
December 7, 2021
Django 3.1.14 fixes a security issue with severity "low" in 3.1.13.
HTTP requests for URLs with trailing newlines could bypass an upstream access control based on URL paths.
CVE-2021-35042: Potential SQL injection via unsanitized QuerySet.order_by() input
July 1, 2021
Django 3.1.13 fixes a security issue with severity "high" in 3.1.12.
QuerySet.order_by() inputUnsanitized user input passed to QuerySet.order_by() could bypass intended
column reference validation in path marked for deprecation resulting in a
potential SQL injection even if a deprecation warning is emitted.
As a mitigation the strict column reference validation was restored for the
duration of the deprecation period. This regression appeared in 3.1 as a side
effect of fixing :ticket:31426.
The issue is not present in the main branch as the deprecated path has been removed.
CVE-2021-33203: Potential directory traversal via admindocs
June 2, 2021
Django 3.1.12 fixes two security issues in 3.1.11.
Staff members could use the ~django.contrib.admindocs TemplateDetailView view to check the existence of arbitrary files. Additionally, if (and only if) the default admindocs templates have been customized by the developers to also expose the file contents, then not only the existence but also the file contents would have been exposed.
As a mitigation, path sanitation is now applied and only files within the template root directories can be loaded.
~django.core.validators.URLValidator, ~django.core.validators.validate_ipv4_address, and ~django.core.validators.validate_ipv46_address didn't prohibit leading zeros in octal literals. If you used such values you could suffer from indeterminate SSRF, RFI, and LFI attacks.
~django.core.validators.validate_ipv4_address and ~django.core.validators.validate_ipv46_address validators were not affected on Python 3.9.5+.
Django 3.1.11 fixes a regression in 3.1.9.
May 13, 2021
Django 3.1.11 fixes a regression in 3.1.9.
Fixed a regression in Django 3.1.9 where saving FileField would raise a SuspiciousFileOperation even when a custom ~django.db.models.FileField.upload_to returns a valid file path (32718).
CVE-2021-32052: Header injection possibility since URLValidator accepted newlines in input on Python 3.9.5+
May 6, 2021
Django 3.1.10 fixes a security issue in 3.1.9.
On Python 3.9.5+, ~django.core.validators.URLValidator didn't prohibit newlines and tabs. If you used values with newlines in HTTP response, you could suffer from header injection attacks. Django itself wasn't vulnerable because ~django.http.HttpResponse prohibits newlines in HTTP headers.
Moreover, the URLField form field which uses URLValidator silently removes newlines and tabs on Python 3.9.5+, so the possibility of newlines entering your data only existed if you are using this validator outside of the form fields.
This issue was introduced by the 43882 fix.
CVE-2021-31542: Potential directory-traversal via uploaded files
May 4, 2021
Django 3.1.9 fixes a security issue in 3.1.8.
MultiPartParser, UploadedFile, and FieldFile allowed
directory-traversal via uploaded files with suitably crafted file names.
In order to mitigate this risk, stricter basename and path sanitation is now applied.
CVE-2021-28658: Potential directory-traversal via uploaded files
April 6, 2021
Django 3.1.8 fixes a security issue with severity "low" and a bug in 3.1.7.
MultiPartParser allowed directory-traversal via uploaded files with suitably crafted file names.
Built-in upload handlers were not affected by this vulnerability.
Fixed a bug in Django 3.1 where the output was hidden on a test error or failure when using test --pdb with the --buffer option (32560).
CVE-2021-23336: Web cache poisoning via django.utils.http.limited_parse_qsl()
February 19, 2021
Django 3.1.7 fixes a security issue and a bug in 3.1.6.
Django contains a copy of urllib.parse.parse_qsl which was added to backport some security fixes. A further security fix has been issued recently such that parse_qsl() no longer allows using ; as a query parameter separator by default. Django now includes this fix. See 42967 for further details.
Fixed a regression in Django 3.1 that caused RuntimeError instead of connection errors when using only the 'postgres' database (32403).
CVE-2021-3281: Potential directory-traversal via archive.extract()
February 1, 2021
Django 3.1.6 fixes a security issue with severity "low" and a bug in 3.1.5.
The django.utils.archive.extract() function, used by startapp --template and startproject --template, allowed directory-traversal via an archive with absolute paths or relative paths with dot segments.
Fixed an admin layout issue in Django 3.1 where changelist filter controls would become squashed (32391).
Django 3.1.5 fixes several bugs in 3.1.4.
January 4, 2021
Django 3.1.5 fixes several bugs in 3.1.4.
Fixed __isnull=True lookup on key transforms for ~django.db.models.JSONField with Oracle and SQLite (32252).
Fixed a bug in Django 3.1 that caused a crash when processing middlewares in an async context with a middleware that raises a MiddlewareNotUsed exception (32299).
Fixed a regression in Django 3.1 that caused the incorrect prefixing of STATIC_URL and MEDIA_URL settings, by the server-provided value of SCRIPT_NAME (or / if not set), when set to a URL specifying the protocol but without a top-level domain, e.g. http://myhost/ (32304).
Django 3.1.4 fixes several bugs in 3.1.3.
December 1, 2020
Django 3.1.4 fixes several bugs in 3.1.3.
Fixed setting the Content-Length HTTP header in AsyncRequestFactory (32162).
Fixed passing extra HTTP headers to AsyncRequestFactory request methods (32159).
Fixed crash of key transforms for ~django.db.models.JSONField on PostgreSQL when using on a Subquery() annotation (32182).
Fixed a regression in Django 3.1 that caused a crash of auto-reloader for certain invocations of runserver on Windows with Python 3.7 and below (32202).
Fixed a regression in Django 3.1 that caused the incorrect grouping by a Q object annotation (32200).
Fixed a regression in Django 3.1 that caused suppressing connection errors when ~django.db.models.JSONField is used on SQLite (32224).
Fixed a crash on SQLite, when QuerySet.values()/values_list() contained key transforms for ~django.db.models.JSONField returning non-string primitive values (32203).
Your coding agent can read these notes before it upgrades. Set up the MCP server →