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 23 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-2024-56374: Potential denial-of-service vulnerability in IPv6 validation
January 14, 2025
Django 5.0.11 fixes a security issue with severity "moderate" in 5.0.10.
Lack of upper bound limit enforcement in strings passed when performing IPv6 validation could lead to a potential denial-of-service attack. The undocumented and private functions clean_ipv6_address and is_valid_ipv6_address were vulnerable, as was the django.forms.GenericIPAddressField form field, which has now been updated to define a max_length of 39 characters.
The django.db.models.GenericIPAddressField model field was not affected.
CVE-2024-53907: Denial-of-service possibility in strip_tags()
December 4, 2024
Django 5.0.10 fixes one security issue with severity "high" and one security issue with severity "moderate" in 5.0.9.
~django.utils.html.strip_tags would be extremely slow to evaluate certain inputs containing large sequences of nested incomplete HTML entities. The strip_tags() method is used to implement the corresponding striptags template filter, which was thus also vulnerable.
strip_tags() now has an upper limit of recursive calls to HTMLParser before raising a .SuspiciousOperation exception.
Remember that absolutely NO guarantee is provided about the results of strip_tags() being HTML safe. So NEVER mark safe the result of a strip_tags() call without escaping it first, for example with django.utils.html.escape.
Direct usage of the django.db.models.fields.json.HasKey lookup on Oracle was subject to SQL injection if untrusted data was used as a lhs value.
Applications that use the has_key lookup through the __ syntax are unaffected.
One column per quarter.
CVE-2024-45230: Potential denial-of-service vulnerability in django.utils.html.urlize()
September 3, 2024
Django 5.0.9 fixes one security issue with severity "moderate" and one security issue with severity "low" in 5.0.8.
urlize and urlizetrunc were subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.
Due to unhandled email sending failures, the ~django.contrib.auth.forms.PasswordResetForm class allowed remote attackers to enumerate user emails by issuing password reset requests and observing the outcomes.
To mitigate this risk, exceptions occurring during password reset email sending are now handled and logged using the django-contrib-auth-logger logger.
CVE-2024-41989: Memory exhaustion in django.utils.numberformat.floatformat()
August 6, 2024
Django 5.0.8 fixes three security issues with severity "moderate", one security issue with severity "high", and several bugs in 5.0.7.
If floatformat received a string representation of a number in scientific notation with a large exponent, it could lead to significant memory consumption.
To avoid this, decimals with more than 200 digits are now returned as is.
urlize and urlizetrunc were subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.
urlize, urlizetrunc, and AdminURLFieldWidget were subject to a potential denial-of-service attack via certain inputs with a very large number of Unicode characters.
.QuerySet.values and ~.QuerySet.values_list methods on models with a JSONField were subject to SQL injection in column aliases, via a crafted JSON object key as a passed *arg.
Added missing validation for UniqueConstraint(nulls_distinct=False) when using *expressions (35594).
Fixed a regression in Django 5.0 where ModelAdmin.action_checkbox could break the admin changelist HTML page when rendering a model instance with a __html__ method (35606).
Fixed a crash when creating a model with a Field.db_default and a Meta.constraints constraint composed of __endswith, __startswith, or __contains lookups (35625).
Fixed a regression in Django 5.0.7 that caused a crash in LocaleMiddleware when processing a language code over 500 characters (35627).
Fixed a bug in Django 5.0 that caused a system check crash when ModelAdmin.date_hierarchy was a GeneratedField with an output_field of DateField or DateTimeField (35628).
Fixed a bug in Django 5.0 which caused constraint validation to either crash or incorrectly raise validation errors for constraints referring to fields using Field.db_default (35638).
Fixed a crash in Django 5.0 when saving a model containing a FileField with a db_default set (35657).
CVE-2024-38875: Potential denial-of-service vulnerability in django.utils.html.urlize()
July 9, 2024
Django 5.0.7 fixes two security issues with severity "moderate", two security issues with severity "low", and one bug in 5.0.6.
urlize and urlizetrunc were subject to a potential denial-of-service attack via certain inputs with a very large number of brackets.
The ~django.contrib.auth.backends.ModelBackend.authenticate method allowed remote attackers to enumerate users via a timing attack involving login requests for users with unusable passwords.
Derived classes of the ~django.core.files.storage.Storage base class which override generate_filename() without replicating the file path validations existing in the parent class, allowed for potential directory-traversal via certain inputs when calling save().
Built-in Storage sub-classes were not affected by this vulnerability.
~django.utils.translation.get_supported_language_variant was subject to a potential denial-of-service attack when used with very long strings containing specific characters.
To mitigate this vulnerability, the language code provided to ~django.utils.translation.get_supported_language_variant is now parsed up to a maximum length of 500 characters.
When the language code is over 500 characters, a ValueError will now be raised if strict is True, or if there is no generic variant and strict is False.
Fixed a bug in Django 5.0 that caused a crash of Model.full_clean() on unsaved model instances with a GeneratedField and certain defined Meta.constraints (35560).
Django 5.0.6 fixes a packaging error in 5.0.5.
May 7, 2024
Django 5.0.6 fixes a packaging error in 5.0.5.
Django 5.0.5 fixes several bugs in 5.0.4.
May 6, 2024
Django 5.0.5 fixes several bugs in 5.0.4.
Fixed a bug in Django 5.0 that caused a crash of Model.save() when
creating an instance of a model with a GeneratedField and providing a
primary key (:ticket:35350).
Fixed a compatibility issue encountered in Python 3.11.9+ and 3.12.3+ when
validating email max line lengths with content decoded using the
surrogateescape error handling scheme (:ticket:35361).
Fixed a bug in Django 5.0 that caused a crash when applying migrations
including alterations to GeneratedField such as setting db_index=True
on SQLite (:ticket:35373).
Allowed importing aprefetch_related_objects from django.db.models
(:ticket:35392).
Fixed a bug in Django 5.0 that caused a migration crash when a
GeneratedField was added before any of the referenced fields from its
expression definition (:ticket:35359).
Fixed a bug in Django 5.0 that caused a migration crash when altering a
GeneratedField referencing a renamed field (:ticket:35422).
Fixed a bug in Django 5.0 where the querysets argument of
GenericPrefetch was not required (:ticket:35426).
Django 5.0.4 fixes several bugs in 5.0.3.
April 3, 2024
Django 5.0.4 fixes several bugs in 5.0.3.
Fixed a bug in Django 5.0 that caused a crash of Model.full_clean() on
fields with expressions in db_default. As a consequence,
Model.full_clean() no longer validates for empty values in fields with
db_default (:ticket:35223).
Fixed a regression in Django 5.0 where the AdminFileWidget could be
rendered with two id attributes on the "Clear" checkbox
(:ticket:35273).
Fixed a bug in Django 5.0 that caused a migration crash on PostgreSQL 15+
when adding a partial UniqueConstraint with nulls_distinct
(:ticket:35329).
Fixed a crash in Django 5.0 when performing queries involving table aliases
and lookups on a GeneratedField of the aliased table (:ticket:35344).
Fixed a bug in Django 5.0 that caused a migration crash when adding a
GeneratedField relying on the __contains or __icontains
lookups or using a Value containing a "%" (:ticket:35336).
CVE-2024-27351: Potential regular expression denial-of-service in django.utils.text.Truncator.words()
March 4, 2024
Django 5.0.3 fixes a security issue with severity "moderate" and several bugs in 5.0.2.
django.utils.text.Truncator.words() method (with html=True) and truncatewords_html template filter were subject to a potential regular expression denial-of-service attack using a suitably crafted string (follow up to 2019-14232 and 2023-43665).
Fixed a regression in Django 5.0.2 where intcomma template filter could return a leading comma for string representation of floats (35172).
Fixed a bug in Django 5.0 that caused a crash of Signal.asend() and asend_robust() when all receivers were asynchronous functions (35174).
Fixed a regression in Django 5.0.1 where .ModelAdmin.lookup_allowed would prevent filtering against foreign keys using lookups like __isnull when the field was not included in .ModelAdmin.list_filter (35173).
Fixed a regression in Django 5.0 that caused a crash of @sensitive_variables and @sensitive_post_parameters decorators on functions loaded from .pyc files (35187).
Fixed a regression in Django 5.0 that caused a crash when reloading a test database and a base queryset for a base manager used prefetch_related() (35238).
Fixed a bug in Django 5.0 where facet filters in the admin would crash on a SimpleListFilter using a queryset without primary keys (35198).
CVE-2024-24680: Potential denial-of-service in intcomma template filter
February 6, 2024
Django 5.0.2 fixes a security issue with severity "moderate" and several bugs in 5.0.1. Also, the latest string translations from Transifex are incorporated.
The intcomma template filter was subject to a potential denial-of-service attack when used with very long strings.
Reallowed, following a regression in Django 5.0.1, filtering against local foreign keys not included in .ModelAdmin.list_filter (35087).
Fixed a regression in Django 5.0 where links in the admin had an incorrect color (35121).
Fixed a bug in Django 5.0 that caused a crash of Model.full_clean() on models with a GeneratedField (35127).
Fixed a regression in Django 5.0 that caused a crash of FilteredRelation() with querysets as right-hand sides (35135). FilteredRelation() now raises a ValueError on querysets as right-hand sides.
Fixed a regression in Django 5.0 that caused a crash of the dumpdata management command when a base queryset used prefetch_related() (35159).
Fixed a regression in Django 5.0 that caused the request_finished signal to sometimes not be fired when running Django through an ASGI server, resulting in potential resource leaks (35059).
Fixed a bug in Django 5.0 that caused a migration crash on MySQL when adding a BinaryField, TextField, JSONField, or GeometryField with a db_default (35162).
Fixed a bug in Django 5.0 that caused a migration crash on models with a literal db_default of a complex type such as dict instance of a JSONField. Running makemigrations might generate no-op AlterField operations for fields using db_default (35149).
Django 5.0.1 fixes several bugs in 5.0.
January 2, 2024
Django 5.0.1 fixes several bugs in 5.0.
Reallowed, following a regression in Django 5.0, using a foreign key to a model with a primary key that is not AutoField in .ModelAdmin.list_filter (35020).
Fixed a long standing bug in handling the RETURNING INTO clause that caused a crash when creating a model instance with a GeneratedField which output_field had backend-specific converters (35024).
Fixed a regression in Django 5.0 that caused a crash of Model.save() for models with both GeneratedField and ForeignKey fields (35019).
Fixed a bug in Django 5.0 that caused a migration crash on Oracle < 23c when adding a GeneratedField with output_field=BooleanField (35018).
Fixed a regression in Django 5.0 where admin fields on the same line could overflow the page and become non-interactive (35012).
Added compatibility for oracledb 2.0.0 (35054).
Fixed a regression in Django 5.0 where querysets referenced incorrect field names from FilteredRelation() (35050).
Fixed a regression in Django 5.0 that caused a system check crash when ModelAdmin.filter_horizontal or filter_vertical contained a reverse many-to-many relation with related_name (35056).
- Django 5.0.14 release notes - Django 5.0.13 release notes - Django 5.0.12 release notes - Django 5.0.11 release notes - Django 5.0.10 release notes
Django 5.0.14 release notes
Django 5.0.13 release notes
Django 5.0.12 release notes
Django 5.0.11 release notes
Django 5.0.10 release notes
Django 5.0.9 release notes
Django 5.0.8 release notes
Django 5.0.7 release notes
Django 5.0.6 release notes
Django 5.0.5 release notes
Django 5.0.4 release notes
Django 5.0.3 release notes
Django 5.0.2 release notes
Django 5.0.1 release notes
Django 5.0 release notes
December 4, 2023
Welcome to Django 5.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 4.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 5.0 supports Python 3.10, 3.11, and 3.12. We highly recommend and only officially support the latest release of each series.
The Django 4.2.x series is the last to support Python 3.8 and 3.9.
Following the release of Django 5.0, we suggest that third-party app authors drop support for all versions of Django prior to 4.2. At that time, you should be able to run your package's tests using python -Wd so that deprecation warnings appear. After making the deprecation warning fixes, your app should be compatible with Django 5.0.
Facet counts are now shown for applied filters in the admin changelist when toggled on via the UI. This behavior can be changed via the new .ModelAdmin.show_facets attribute. For more information see facet-filters.
Django 5.0 introduces the concept of a field group, and field group templates. This simplifies rendering of the related elements of a Django form field such as its label, widget, help text, and errors.
For example, the template below:
<form>
...
<div>
{{ form.name.label_tag }}
{% if form.name.help_text %}
<div class="helptext" id="{{ form.name.auto_id }}_helptext">
{{ form.name.help_text|safe }}
</div>
{% endif %}
{{ form.name.errors }}
{{ form.name }}
<div class="row">
<div class="col">
{{ form.email.label_tag }}
{% if form.email.help_text %}
<div class="helptext" id="{{ form.email.auto_id }}_helptext">
{{ form.email.help_text|safe }}
</div>
{% endif %}
{{ form.email.errors }}
{{ form.email }}
</div>
<div class="col">
{{ form.password.label_tag }}
{% if form.password.help_text %}
<div class="helptext" id="{{ form.password.auto_id }}_helptext">
{{ form.password.help_text|safe }}
</div>
{% endif %}
{{ form.password.errors }}
{{ form.password }}
</div>
</div>
</div>
...
</form>
Can now be simplified to:
<form>
...
<div>
{{ form.name.as_field_group }}
<div class="row">
<div class="col">{{ form.email.as_field_group }}</div>
<div class="col">{{ form.password.as_field_group }}</div>
</div>
</div>
...
</form>
~django.forms.BoundField.as_field_group renders fields with the "django/forms/field.html" template by default and can be customized on a per-project, per-field, or per-request basis. See reusable-field-group-templates.
The new Field.db_default parameter sets a database-computed default value. For example:
from django.db import models
from django.db.models.functions import Now, Pi
class MyModel(models.Model):
age = models.IntegerField(db_default=18)
created = models.DateTimeField(db_default=Now())
circumference = models.FloatField(db_default=2 * Pi())
The new ~django.db.models.GeneratedField allows creation of database generated columns. This field can be used on all supported database backends to create a field that is always computed from other fields. For example:
from django.db import models
from django.db.models import F
class Square(models.Model):
side = models.IntegerField()
area = models.GeneratedField(
expression=F("side") * F("side"),
output_field=models.BigIntegerField(),
db_persist=True,
)
.Field.choices (for model fields) and .ChoiceField.choices (for form fields) allow for more flexibility when declaring their values. In previous versions of Django, choices should either be a list of 2-tuples, or an field-choices-enum-types subclass, but the latter required accessing the .choices attribute to provide the values in the expected form:
from django.db import models
Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")
SPORT_CHOICES = [
("Martial Arts", [("judo", "Judo"), ("karate", "Karate")]),
("Racket", [("badminton", "Badminton"), ("tennis", "Tennis")]),
("unknown", "Unknown"),
]
class Winner(models.Model):
name = models.CharField(...)
medal = models.CharField(..., choices=Medal.choices)
sport = models.CharField(..., choices=SPORT_CHOICES)
Django 5.0 adds support for accepting a mapping or a callable instead of an iterable, and also no longer requires .choices to be used directly to expand enumeration types:
from django.db import models
Medal = models.TextChoices("Medal", "GOLD SILVER BRONZE")
SPORT_CHOICES = { # Using a mapping instead of a list of 2-tuples.
"Martial Arts": {"judo": "Judo", "karate": "Karate"},
"Racket": {"badminton": "Badminton", "tennis": "Tennis"},
"unknown": "Unknown",
}
def get_scores():
return [(i, str(i)) for i in range(10)]
class Winner(models.Model):
name = models.CharField(...)
medal = models.CharField(..., choices=Medal) # Using `.choices` not required.
sport = models.CharField(..., choices=SPORT_CHOICES)
score = models.IntegerField(choices=get_scores) # A callable is allowed.
Under the hood the provided choices are normalized into a list of 2-tuples as the canonical form whenever the choices value is updated. For more information, please check the model field reference on choices.
The new .AdminSite.get_log_entries method allows customizing the queryset for the site's listed log entries.
The django.contrib.admin.AllValuesFieldListFilter, ChoicesFieldListFilter, RelatedFieldListFilter, and RelatedOnlyFieldListFilter admin filters now handle multi-valued query parameters.
XRegExp is upgraded from version 3.2.0 to 5.1.1.
The new .AdminSite.get_model_admin method returns an admin class for the given model class.
Properties in .ModelAdmin.list_display now support boolean attribute.
jQuery is upgraded from version 3.6.4 to 3.7.1.
The default iteration count for the PBKDF2 password hasher is increased from 600,000 to 720,000.
The new asynchronous functions are now provided, using an a prefix: django.contrib.auth.aauthenticate, ~.django.contrib.auth.aget_user, ~.django.contrib.auth.alogin, ~.django.contrib.auth.alogout, and ~.django.contrib.auth.aupdate_session_auth_hash.
AuthenticationMiddleware now adds an .HttpRequest.auser asynchronous method that returns the currently logged-in user.
The new django.contrib.auth.hashers.acheck_password asynchronous function and .AbstractBaseUser.acheck_password method allow asynchronous checking of user passwords.
.QuerySet.prefetch_related now supports prefetching ~django.contrib.contenttypes.fields.GenericForeignKey with non-homogeneous set of results.
The new ClosestPoint() function returns a 2-dimensional point on the geometry that is closest to another geometry.
GIS aggregates now support the filter argument.
Support for GDAL 3.7 and GEOS 3.12 is added.
The new .GEOSGeometry.equals_identical method allows point-wise equivalence checking of geometries.
The new .MessagesTestMixin.assertMessages assertion method allows testing ~django.contrib.messages added to a response.
The new ~.ExclusionConstraint.violation_error_code attribute of ~django.contrib.postgres.constraints.ExclusionConstraint allows customizing the code of ValidationError raised during model validation.
Under ASGI, http.disconnect events are now handled. This allows views to perform any necessary cleanup if a client disconnects before the response is generated. See async-handling-disconnect for more details.
The following decorators now support wrapping asynchronous view functions:
~django.views.decorators.cache.cache_control
~django.views.decorators.cache.never_cache
~django.views.decorators.common.no_append_slash
~django.views.decorators.csrf.csrf_exempt
~django.views.decorators.csrf.csrf_protect
~django.views.decorators.csrf.ensure_csrf_cookie
~django.views.decorators.csrf.requires_csrf_token
~django.views.decorators.debug.sensitive_variables
~django.views.decorators.debug.sensitive_post_parameters
~django.views.decorators.gzip.gzip_page
~django.views.decorators.http.condition
conditional_page()
~django.views.decorators.http.etag
~django.views.decorators.http.last_modified
~django.views.decorators.http.require_http_methods
~django.views.decorators.http.require_GET
~django.views.decorators.http.require_POST
~django.views.decorators.http.require_safe
~django.views.decorators.vary.vary_on_cookie
~django.views.decorators.vary.vary_on_headers
xframe_options_deny()
xframe_options_sameorigin()
xframe_options_exempt()
~django.views.decorators.debug.sensitive_variables and ~django.views.decorators.debug.sensitive_post_parameters can now be used with asynchronous functions.
.File.open now passes all positional (*args) and keyword arguments (**kwargs) to Python's built-in python:open.
The new ~django.forms.URLField.assume_scheme argument for ~django.forms.URLField allows specifying a default URL scheme.
In order to improve accessibility, the following changes are made:
Form fields now include the aria-describedby HTML attribute to enable screen readers to associate form fields with their help text.
Invalid form fields now include the aria-invalid="true" HTML attribute.
Support and translations for the Uyghur language are now available.
Serialization of functions decorated with functools.cache or functools.lru_cache is now supported without the need to write a custom serializer.
The new create_defaults argument of .QuerySet.update_or_create and .QuerySet.aupdate_or_create methods allows specifying a different field values for the create operation.
The new violation_error_code attribute of ~django.db.models.BaseConstraint, ~django.db.models.CheckConstraint, and ~django.db.models.UniqueConstraint allows customizing the code of ValidationError raised during model validation.
The force_insert argument of .Model.save now allows specifying a tuple of parent classes that must be forced to be inserted.
.QuerySet.bulk_create and .QuerySet.abulk_create methods now set the primary key on each model instance when the update_conflicts parameter is enabled (if the database supports it).
The new .UniqueConstraint.nulls_distinct attribute allows customizing the treatment of NULL values on PostgreSQL 15+.
The new ~django.shortcuts.aget_object_or_404 and ~django.shortcuts.aget_list_or_404 asynchronous shortcuts allow asynchronous getting objects.
The new ~django.db.models.aprefetch_related_objects function allows asynchronous prefetching of model instances.
.QuerySet.aiterator now supports previous calls to prefetch_related().
On MariaDB 10.7+, UUIDField is now created as UUID column rather than CHAR(32) column. See the migration guide above for more details on migrating-uuidfield.
Django now supports oracledb version 1.3.2 or higher. Support for cx_Oracle is deprecated as of this release and will be removed in Django 6.0.
The new django.core.paginator.Paginator.error_messages argument allows customizing the error messages raised by .Paginator.page.
The new .Signal.asend and .Signal.asend_robust methods allow asynchronous signal dispatch. Signal receivers may be synchronous or asynchronous, and will be automatically adapted to the correct calling style.
The new escapeseq template filter applies escape to each element of a sequence.
~django.test.Client and ~django.test.AsyncClient now provide asynchronous methods, using an a prefix: ~django.test.Client.asession, ~django.test.Client.alogin, ~django.test.Client.aforce_login, and ~django.test.Client.alogout.
~django.test.AsyncClient now supports the follow parameter.
~django.test.runner.DiscoverRunner now allows showing the duration of the slowest tests using the test --durations option (available on Python 3.12+).
The new offset argument of ~django.core.validators.StepValueValidator allows specifying an offset for valid values.
This section describes changes that may be needed in third-party database backends.
DatabaseFeatures.supports_expression_defaults should be set to False if the database doesn't support using database functions as defaults.
DatabaseFeatures.supports_default_keyword_in_insert should be set to False if the database doesn't support the DEFAULT keyword in INSERT queries.
DatabaseFeatures.supports_default_keyword_in_bulk_insert should be set to False if the database doesn't support the DEFAULT keyword in bulk INSERT queries.
Support for GDAL 2.2 and 2.3 is removed.
Support for GEOS 3.6 and 3.7 is removed.
The django.contrib.sitemaps.ping_google() function and the ping_google management command are removed as the Google Sitemaps ping endpoint is deprecated and will be removed in January 2024.
The django.contrib.sitemaps.SitemapNotFound exception class is removed.
Support for pre-releases of MySQL 8.0.x series is removed. Django 5.0 supports MySQL 8.0.11 and higher.
.QuerySet.update_or_create now supports the parameter create_defaults. As a consequence, any models that have a field named create_defaults that are used with an update_or_create() should specify the field in the lookup with create_defaults__exact.
On MariaDB 10.7+, UUIDField is now created as UUID column rather than CHAR(32) column. As a consequence, any UUIDField created in Django < 5.0 should be replaced with a UUIDField subclass backed by CHAR(32):
class Char32UUIDField(models.UUIDField):
def db_type(self, connection):
return "char(32)"
def get_db_prep_value(self, value, connection, prepared=False):
value = super().get_db_prep_value(value, connection, prepared)
if value is not None:
value = value.hex
return value
For example:
class MyModel(models.Model):
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
Should become:
class Char32UUIDField(models.UUIDField): ...
class MyModel(models.Model):
uuid = Char32UUIDField(primary_key=True, default=uuid.uuid4)
Running the makemigrations command will generate a migration containing a no-op AlterField operation.
The instance argument of the undocumented BaseModelFormSet.save_existing() method is renamed to obj.
The undocumented django.contrib.admin.helpers.checkbox is removed.
Integer fields are now validated as 64-bit integers on SQLite to match the behavior of sqlite3.
The undocumented Query.annotation_select_mask attribute is changed from a set of strings to an ordered list of strings.
ImageField.update_dimension_fields() is no longer called on the post_init signal if width_field and height_field are not set.
~django.db.models.functions.Now database function now uses LOCALTIMESTAMP instead of CURRENT_TIMESTAMP on Oracle.
.AdminSite.site_header is now rendered in a <div> tag instead of <h1>. Screen reader users rely on heading elements for navigation within a page. Having two <h1> elements was confusing and the site header wasn't helpful as it is repeated on all pages.
In order to improve accessibility, the admin's main content area and header content area are now rendered in a <main> and <header> tag instead of <div>.
On databases without native support for the SQL XOR operator, ^ as the exclusive or (XOR) operator now returns rows that are matched by an odd number of operands rather than exactly one operand. This is consistent with the behavior of MySQL, MariaDB, and Python.
The minimum supported version of asgiref is increased from 3.6.0 to 3.7.0.
The minimum supported version of selenium is increased from 3.8.0 to 4.8.0.
The AlreadyRegistered and NotRegistered exceptions are moved from django.contrib.admin.sites to django.contrib.admin.exceptions.
The minimum supported version of SQLite is increased from 3.21.0 to 3.27.0.
Support for cx_Oracle < 8.3 is removed.
Executing SQL queries before the app registry has been fully populated now raises RuntimeWarning.
~django.core.exceptions.BadRequest is raised for non-UTF-8 encoded requests with the application/x-www-form-urlencoded content type. See 1866 for more details.
The minimum supported version of colorama is increased to 0.4.6.
The minimum supported version of docutils is increased to 0.19.
Filtering querysets against overflowing integer values now always returns an empty queryset. As a consequence, you may need to use ExpressionWrapper() to explicitly wrap arithmetic against integer fields in such cases.
The DjangoDivFormRenderer and Jinja2DivFormRenderer transitional form renderers are deprecated.
Passing positional arguments name and violation_error_message to ~django.db.models.BaseConstraint is deprecated in favor of keyword-only arguments.
request is added to the signature of .ModelAdmin.lookup_allowed. Support for ModelAdmin subclasses that do not accept this argument is deprecated.
The get_joining_columns() method of ForeignObject and ForeignObjectRel is deprecated. Starting with Django 6.0, django.db.models.sql.datastructures.Join will no longer fallback to get_joining_columns(). Subclasses should implement get_joining_fields() instead.
The ForeignObject.get_reverse_joining_columns() method is deprecated.
The default scheme for forms.URLField will change from "http" to "https" in Django 6.0. Set FORMS_URLFIELD_ASSUME_HTTPS transitional setting to True to opt into assuming "https" during the Django 5.x release cycle.
FORMS_URLFIELD_ASSUME_HTTPS transitional setting is deprecated.
Support for calling format_html() without passing args or kwargs is deprecated.
Support for cx_Oracle is deprecated in favor of oracledb 1.3.2+ Python driver.
DatabaseOperations.field_cast_sql() is deprecated in favor of DatabaseOperations.lookup_cast(). Starting with Django 6.0, BuiltinLookup.process_lhs() will no longer call field_cast_sql(). Third-party database backends should implement lookup_cast() instead.
The django.db.models.enums.ChoicesMeta metaclass is renamed to ChoicesType.
The Prefetch.get_current_queryset() method is deprecated.
The get_prefetch_queryset() method of related managers and descriptors is deprecated. Starting with Django 6.0, get_prefetcher() and prefetch_related_objects() will no longer fallback to get_prefetch_queryset(). Subclasses should implement get_prefetch_querysets() instead.
These features have reached the end of their deprecation cycle and are removed in Django 5.0.
See deprecated-features-4.0 for details on these changes, including how to remove usage of these features.
The SERIALIZE test setting is removed.
The undocumented django.utils.baseconv module is removed.
The undocumented django.utils.datetime_safe module is removed.
The default value of the USE_TZ setting is changed from False to True.
The default sitemap protocol for sitemaps built outside the context of a request is changed from 'http' to 'https'.
The extra_tests argument for DiscoverRunner.build_suite() and DiscoverRunner.run_tests() is removed.
The django.contrib.postgres.aggregates.ArrayAgg, JSONBAgg, and StringAgg aggregates no longer return [], [], and '', respectively, when there are no rows.
The USE_L10N setting is removed.
The USE_DEPRECATED_PYTZ transitional setting is removed.
Support for pytz timezones is removed.
The is_dst argument is removed from:
QuerySet.datetimes()
django.utils.timezone.make_aware()
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()
The django.contrib.gis.admin.GeoModelAdmin and OSMGeoAdmin classes are removed.
The undocumented BaseForm._html_output() method is removed.
The ability to return a str, rather than a SafeString, when rendering an ErrorDict and ErrorList is removed.
See deprecated-features-4.1 for details on these changes, including how to remove usage of these features.
The SitemapIndexItem.__str__() method is removed.
The CSRF_COOKIE_MASKED transitional setting is removed.
The name argument of django.utils.functional.cached_property() is removed.
The opclasses argument of django.contrib.postgres.constraints.ExclusionConstraint is removed.
The undocumented ability to pass errors=None to SimpleTestCase.assertFormError() and assertFormsetError() is removed.
django.contrib.sessions.serializers.PickleSerializer is removed.
The usage of QuerySet.iterator() on a queryset that prefetches related objects without providing the chunk_size argument is no longer allowed.
Passing unsaved model instances to related filters is no longer allowed.
created=True is required in the signature of RemoteUserBackend.configure_user() subclasses.
Support for logging out via GET requests in the django.contrib.auth.views.LogoutView and django.contrib.auth.views.logout_then_login() is removed.
The django.utils.timezone.utc alias to datetime.timezone.utc is removed.
Passing a response object and a form/formset name to SimpleTestCase.assertFormError() and assertFormSetError() is no longer allowed.
The django.contrib.gis.admin.OpenLayersWidget is removed.
The django.contrib.auth.hashers.CryptPasswordHasher is removed.
The "django/forms/default.html" and "django/forms/formsets/default.html" templates are removed.
The default form and formset rendering style is changed to the div-based.
Passing nulls_first=False or nulls_last=False to Expression.asc() and Expression.desc() methods, and the OrderBy expression is no longer allowed.
Nothing published for this version
Nothing published for this version
Nothing published for this version
CVE-2026-3902: ASGI header spoofing via underscore/hyphen conflation
April 7, 2026
Django 4.2.30 fixes one security issue with severity "moderate" and four security issues with severity "low" in 4.2.29.
ASGIRequest normalizes header names following WSGI conventions, mapping hyphens to underscores. As a result, even in configurations where reverse proxies carefully strip security-sensitive headers named with hyphens, such a header could be spoofed by supplying a header named with underscores.
Under WSGI, it is the responsibility of the server or proxy to avoid ambiguous mappings. (Django's runserver was patched in 2015-0219.) But under ASGI, there is not the same uniform expectation, even if many proxies protect against this under default configuration (including nginx via underscores_in_headers off;).
Headers containing underscores are now ignored by ASGIRequest, matching the behavior of Daphne, the reference server for ASGI.
This issue has severity "low" according to the Django security policy.
Add permissions on inline model instances were not validated on submission of forged POST data in ~django.contrib.contenttypes.admin.GenericInlineModelAdmin.
This issue has severity "low" according to the Django security policy.
Admin changelist forms using ~django.contrib.admin.ModelAdmin.list_editable incorrectly allowed new instances to be created via forged POST data.
This issue has severity "low" according to the Django security policy.
When using django.http.multipartparser.MultiPartParser, multipart uploads with Content-Transfer-Encoding: base64 that include excessive whitespace may trigger repeated memory copying, potentially degrading performance.
This issue has severity "moderate" according to the Django security policy.
ASGI requests with a missing or understated Content-Length header could bypass the DATA_UPLOAD_MAX_MEMORY_SIZE limit when reading HttpRequest.body, potentially loading an unbounded request body into memory and causing service degradation.
This issue has severity "low" according to the Django security policy.
CVE-2026-25673: Potential denial-of-service vulnerability in URLField via Unicode normalization on Windows
March 3, 2026
Django 4.2.29 fixes a security issue with severity "moderate" and a security issue with severity "low" in 4.2.28.
The ~django.forms.URLField form field's to_python() method used ~urllib.parse.urlsplit to determine whether to prepend a URL scheme to the submitted value. On Windows, urlsplit() performs NFKC normalization, which can be disproportionately slow for large inputs containing certain characters.
URLField.to_python() now uses a simplified scheme detection, avoiding Unicode normalization entirely and deferring URL validation to the appropriate layers. As a result, while leading and trailing whitespace is still stripped by default, characters such as newlines, tabs, and other control characters within the value are no longer handled by URLField.to_python(). When using the default ~django.core.validators.URLValidator, these values will continue to raise ~django.core.exceptions.ValidationError during validation, but if you rely on custom validators, ensure they do not depend on the previous behavior of URLField.to_python().
This issue has severity "moderate" according to the Django security policy.
Django's file-system storage and file-based cache backends used the process umask to control permissions when creating directories. In multi-threaded environments, one thread's temporary umask change can affect other threads' file and directory creation, resulting in file system objects being created with unintended permissions.
Django now applies the requested permissions via ~os.chmod after ~os.mkdir, removing the dependency on the process-wide umask.
This issue has severity "low" according to the Django security policy.
CVE-2025-13473: Username enumeration through timing difference in mod_wsgi authentication handler
February 3, 2026
Django 4.2.28 fixes three security issues with severity "high", two security issues with severity "moderate", and one security issue with severity "low" in 4.2.27.
The django.contrib.auth.handlers.modwsgi.check_password() function for authentication via mod_wsgi allowed remote attackers to enumerate users via a timing attack.
This issue has severity "low" according to the Django security policy.
When receiving duplicates of a single header, ASGIRequest allowed a remote attacker to cause a potential denial-of-service via a specifically created request with multiple duplicate headers. The vulnerability resulted from repeated string concatenation while combining repeated headers, which produced super-linear computation resulting in service degradation or outage.
This issue has severity "moderate" according to the Django security policy.
Raster lookups on GIS fields (only implemented on PostGIS) were subject to SQL injection if untrusted data was used as a band index.
As a reminder, all untrusted user input should be validated before use.
This issue has severity "high" according to the Django security policy.
django.utils.text.Truncator.chars() and Truncator.words() methods (with html=True) and the truncatechars_html and truncatewords_html template filters were subject to a potential denial-of-service attack via certain inputs with a large number of unmatched HTML end tags, which could cause quadratic time complexity during HTML parsing.
This issue has severity "moderate" according to the Django security policy.
.FilteredRelation was subject to SQL injection in column aliases via control characters, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to .QuerySet.annotate, ~.QuerySet.aggregate, ~.QuerySet.extra, ~.QuerySet.values, ~.QuerySet.values_list, and ~.QuerySet.alias.
This issue has severity "high" according to the Django security policy.
.QuerySet.order_by was subject to SQL injection in column aliases containing periods when the same alias was, using a suitably crafted dictionary, with dictionary expansion, used in .FilteredRelation.
This issue has severity "high" according to the Django security policy.
CVE-2025-13372: Potential SQL injection in FilteredRelation column aliases on PostgreSQL
December 2, 2025
Django 4.2.27 fixes one security issue with severity "high", one security issue with severity "moderate", and one bug in 4.2.26.
.FilteredRelation was subject to SQL injection in column aliases, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to .QuerySet.annotate or .QuerySet.alias on PostgreSQL.
XML Serialization was subject to a potential denial-of-service attack due to quadratic time complexity when deserializing crafted documents containing many nested invalid elements. The internal helper django.core.serializers.xml_serializer.getInnerText() previously accumulated inner text inefficiently during recursion. It now collects text per element, avoiding excessive resource usage.
Fixed a regression in Django 4.2.26 where DisallowedRedirect was raised by ~django.http.HttpResponseRedirect and ~django.http.HttpResponsePermanentRedirect for URLs longer than 2048 characters. The limit is now 16384 characters (36743).
CVE-2025-64458: Potential denial-of-service vulnerability in HttpResponseRedirect and HttpResponsePermanentRedirect on Windows
November 5, 2025
Django 4.2.26 fixes one security issue with severity "high" and one security issue with severity "moderate" in 4.2.25.
Python's NFKC normalization is slow on Windows. As a consequence, ~django.http.HttpResponseRedirect, ~django.http.HttpResponsePermanentRedirect, and the shortcut redirect() were subject to a potential denial-of-service attack via certain inputs with a very large number of Unicode characters (follow up to 2025-27556).
.QuerySet.filter, ~.QuerySet.exclude, ~.QuerySet.get, and ~.Q were subject to SQL injection using a suitably crafted dictionary, with dictionary expansion, as the _connector argument.
CVE-2025-59681: Potential SQL injection in QuerySet.annotate(), alias(), aggregate(), and extra() on MySQL and MariaDB
October 1, 2025
Django 4.2.25 fixes one security issue with severity "high" and one security issue with severity "low" in 4.2.24.
.QuerySet.annotate, ~.QuerySet.alias, ~.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 (follow up to 2022-28346).
The django.utils.archive.extract() function, used by startapp --template and startproject --template, allowed partial directory-traversal via an archive with file paths sharing a common prefix with the target directory (follow up to 2021-3281).
CVE-2025-57833: Potential SQL injection in FilteredRelation column aliases
September 3, 2025
Django 4.2.24 fixes a security issue with severity "high" in 4.2.23.
.FilteredRelation was subject to SQL injection in column aliases, using a suitably crafted dictionary, with dictionary expansion, as the **kwargs passed to .QuerySet.annotate or .QuerySet.alias.
Django 4.2.23 fixes a potential log injection issue in 4.2.22.
June 10, 2025
Django 4.2.23 fixes a potential log injection issue in 4.2.22.
django.utils.log.log_response(), which safely escapes arguments such
as the request path to prevent unsafe log output (:cve:2025-48432).CVE-2025-48432: Potential log injection via unescaped request path
June 4, 2025
Django 4.2.22 fixes a security issue with severity "low" in 4.2.21.
Internal HTTP response logging used request.path directly, allowing control
characters (e.g. newlines or ANSI escape sequences) to be written unescaped
into logs. This could enable log injection or forgery, letting attackers
manipulate log appearance or structure, especially in logs processed by
external systems or viewed in terminals.
Although this does not directly impact Django's security model, it poses risks
when logs are consumed or interpreted by other tools. To fix this, the internal
django.utils.log.log_response() function now escapes all positional
formatting arguments using a safe encoding.
CVE-2025-32873: Denial-of-service possibility in strip_tags()
May 7, 2025
Django 4.2.21 fixes a security issue with severity "moderate", a data loss bug, and a regression in 4.2.20.
This release was built using an upgraded setuptools, producing filenames compliant with 491 and 625 and thus addressing a PyPI warning about non-compliant distribution filenames. This change only affects the Django packaging process and does not impact Django's behavior.
~django.utils.html.strip_tags would be slow to evaluate certain inputs containing large sequences of incomplete HTML tags. This function is used to implement the striptags template filter, which was thus also vulnerable.
~django.utils.html.strip_tags now raises a .SuspiciousOperation exception if it encounters an unusually large number of unclosed opening tags.
Fixed a data corruption possibility in file_move_safe() when allow_overwrite=True, where leftover content from a previously larger file could remain after overwriting with a smaller one due to lack of truncation (36298).
Fixed a regression in Django 4.2.20, introduced when fixing 2025-26699, where the wordwrap template filter did not preserve empty lines between paragraphs after wrapping text (36341).
CVE-2025-26699: Potential denial-of-service vulnerability in django.utils.text.wrap()
March 6, 2025
Django 4.2.20 fixes a security issue with severity "moderate" in 4.2.19.
django.utils.text.wrap()The wrap() and :tfilter:wordwrap template filter were subject to a
potential denial-of-service attack when used with very long strings.
Django 4.2.19 fixes a regression in 4.2.18.
February 5, 2025
Django 4.2.19 fixes a regression in 4.2.18.
validate_ipv6_address()
and validate_ipv46_address() to crash when handling non-string values
(:ticket:36098).CVE-2024-56374: Potential denial-of-service vulnerability in IPv6 validation
January 14, 2025
Django 4.2.18 fixes a security issue with severity "moderate" in 4.2.17.
Lack of upper bound limit enforcement in strings passed when performing IPv6 validation could lead to a potential denial-of-service attack. The undocumented and private functions clean_ipv6_address and is_valid_ipv6_address were vulnerable, as was the django.forms.GenericIPAddressField form field, which has now been updated to define a max_length of 39 characters.
The django.db.models.GenericIPAddressField model field was not affected.
CVE-2024-53907: Denial-of-service possibility in strip_tags()
December 4, 2024
Django 4.2.17 fixes one security issue with severity "high" and one security issue with severity "moderate" in 4.2.16.
~django.utils.html.strip_tags would be extremely slow to evaluate certain inputs containing large sequences of nested incomplete HTML entities. The strip_tags() method is used to implement the corresponding striptags template filter, which was thus also vulnerable.
strip_tags() now has an upper limit of recursive calls to HTMLParser before raising a .SuspiciousOperation exception.
Remember that absolutely NO guarantee is provided about the results of strip_tags() being HTML safe. So NEVER mark safe the result of a strip_tags() call without escaping it first, for example with django.utils.html.escape.
Direct usage of the django.db.models.fields.json.HasKey lookup on Oracle was subject to SQL injection if untrusted data was used as a lhs value.
Applications that use the has_key lookup through the __ syntax are unaffected.
CVE-2024-45230: Potential denial-of-service vulnerability in django.utils.html.urlize()
September 3, 2024
Django 4.2.16 fixes one security issue with severity "moderate" and one security issue with severity "low" in 4.2.15.
urlize and urlizetrunc were subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.
Due to unhandled email sending failures, the ~django.contrib.auth.forms.PasswordResetForm class allowed remote attackers to enumerate user emails by issuing password reset requests and observing the outcomes.
To mitigate this risk, exceptions occurring during password reset email sending are now handled and logged using the django-contrib-auth-logger logger.
CVE-2024-41989: Memory exhaustion in django.utils.numberformat.floatformat()
August 6, 2024
Django 4.2.15 fixes three security issues with severity "moderate", one security issue with severity "high", and a regression in 4.2.14.
If floatformat received a string representation of a number in scientific notation with a large exponent, it could lead to significant memory consumption.
To avoid this, decimals with more than 200 digits are now returned as is.
urlize and urlizetrunc were subject to a potential denial-of-service attack via very large inputs with a specific sequence of characters.
urlize, urlizetrunc, and AdminURLFieldWidget were subject to a potential denial-of-service attack via certain inputs with a very large number of Unicode characters.
.QuerySet.values and ~.QuerySet.values_list methods on models with a JSONField were subject to SQL injection in column aliases, via a crafted JSON object key as a passed *arg.
Fixed a regression in Django 4.2.14 that caused a crash in LocaleMiddleware when processing a language code over 500 characters (35627).
CVE-2024-38875: Potential denial-of-service vulnerability in django.utils.html.urlize()
July 9, 2024
Django 4.2.14 fixes two security issues with severity "moderate" and two security issues with severity "low" in 4.2.13.
urlize and urlizetrunc were subject to a potential denial-of-service attack via certain inputs with a very large number of brackets.
The ~django.contrib.auth.backends.ModelBackend.authenticate method allowed remote attackers to enumerate users via a timing attack involving login requests for users with unusable passwords.
Derived classes of the ~django.core.files.storage.Storage base class which override generate_filename() without replicating the file path validations existing in the parent class, allowed for potential directory-traversal via certain inputs when calling save().
Built-in Storage sub-classes were not affected by this vulnerability.
~django.utils.translation.get_supported_language_variant was subject to a potential denial-of-service attack when used with very long strings containing specific characters.
To mitigate this vulnerability, the language code provided to ~django.utils.translation.get_supported_language_variant is now parsed up to a maximum length of 500 characters.
When the language code is over 500 characters, a ValueError will now be raised if strict is True, or if there is no generic variant and strict is False.
Django 4.2.13 fixes a packaging error in 4.2.12.
May 7, 2024
Django 4.2.13 fixes a packaging error in 4.2.12.
Django 4.2.12 fixes a compatibility issue with Python 3.11.9+ and 3.12.3+.
May 6, 2024
Django 4.2.12 fixes a compatibility issue with Python 3.11.9+ and 3.12.3+.
surrogateescape error handling scheme
(:ticket:35361).CVE-2024-27351: Potential regular expression denial-of-service in django.utils.text.Truncator.words()
March 4, 2024
Django 4.2.11 fixes a security issue with severity "moderate" and a regression in 4.2.10.
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 4.2.10 fixes a security issue with severity "moderate" in 4.2.9.
intcomma template filterThe intcomma template filter was subject to a potential denial-of-service
attack when used with very long strings.
Django 4.2.9 fixes a bug in 4.2.8.
January 2, 2024
Django 4.2.9 fixes a bug in 4.2.8.
35012).Django 4.2.8 fixes several bugs in 4.2.7 and adds compatibility with Python 3.12.
December 4, 2023
Django 4.2.8 fixes several bugs in 4.2.7 and adds compatibility with Python 3.12.
Fixed a regression in Django 4.2 that caused makemigrations --check to stop displaying pending migrations (34457).
Fixed a regression in Django 4.2 that caused a crash of QuerySet.aggregate() with aggregates referencing other aggregates or window functions through conditional expressions (34975).
Fixed a regression in Django 4.2 that caused a crash when annotating a QuerySet with a Window expressions composed of a partition_by clause mixing field types and aggregation expressions (34987).
Fixed a regression in Django 4.2 where the admin's change list page had misaligned pagination links and inputs when using list_editable (34991).
Fixed a regression in Django 4.2 where checkboxes in the admin would be centered on narrower screen widths (34994).
Fixed a regression in Django 4.2 that caused a crash of querysets with aggregations on MariaDB when the ONLY_FULL_GROUP_BY SQL mode was enabled (34992).
Fixed a regression in Django 4.2 where the admin's read-only password widget and some help texts were incorrectly aligned at tablet widths (34982).
Fixed a regression in Django 4.2 that caused a migration crash on SQLite when altering unsupported Meta.db_table_comment (35006).
CVE-2023-46695: Potential denial of service vulnerability in UsernameField on Windows
November 1, 2023
Django 4.2.7 fixes a security issue with severity "moderate" and several bugs in 4.2.6.
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.
Fixed a regression in Django 4.2 that caused a crash of QuerySet.aggregate() with aggregates referencing expressions containing subqueries (34798).
Restored, following a regression in Django 4.2, creating varchar/text_pattern_ops indexes on CharField and TextField with deterministic collations on PostgreSQL (34932).
CVE-2023-43665: Denial-of-service possibility in django.utils.text.Truncator
October 4, 2023
Django 4.2.6 fixes a security issue with severity "moderate" and several bugs in 4.2.5.
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.
Fixed a regression in Django 4.2.5 where overriding the deprecated
DEFAULT_FILE_STORAGE and STATICFILES_STORAGE settings in tests caused
the main STORAGES to mutate (:ticket:34821).
Fixed a regression in Django 4.2 that caused unnecessary casting of string
based fields (CharField, EmailField, TextField, CICharField,
CIEmailField, and CITextField) used with the __isnull lookup on
PostgreSQL. As a consequence, indexes using an __isnull expression or
condition created before Django 4.2 wouldn't be used by the query planner,
leading to a performance regression (:ticket:34840).
You may need to recreate such indexes created in your database with Django
4.2 to 4.2.5, as they contain unnecessary ::text casting. Find candidate
indexes with this query:
.. code-block:: sql
SELECT indexname, indexdef
FROM pg_indexes
WHERE indexdef LIKE '%::text IS %NULL';
CVE-2023-41164: Potential denial of service vulnerability in django.utils.encoding.uri_to_iri()
September 4, 2023
Django 4.2.5 fixes a security issue with severity "moderate" and several bugs in 4.2.4.
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.
Fixed a regression in Django 4.2 that caused an incorrect validation of
CheckConstraints on __isnull lookups against JSONField
(:ticket:34754).
Fixed a bug in Django 4.2 where the deprecated DEFAULT_FILE_STORAGE and
STATICFILES_STORAGE settings were not synced with STORAGES
(:ticket:34773).
Fixed a regression in Django 4.2.2 that caused an unnecessary selection of a
non-nullable ManyToManyField without a natural key during serialization
(:ticket:34779).
Fixed a regression in Django 4.2 that caused a crash of a queryset when
filtering against deeply nested OuterRef() annotations (:ticket:34803).
Django 4.2.4 fixes several bugs in 4.2.3.
August 1, 2023
Django 4.2.4 fixes several bugs in 4.2.3.
Fixed a regression in Django 4.2 that caused a crash of
QuerySet.aggregate() with aggregates referencing window functions
(:ticket:34717).
Fixed a regression in Django 4.2 that caused a crash when grouping by a
reference in a subquery (:ticket:34748).
Fixed a regression in Django 4.2 that caused aggregation over query that
uses explicit grouping by multi-valued annotations to group against the wrong
columns (:ticket:34750).
CVE-2023-36053: Potential regular expression denial of service vulnerability in EmailValidator/URLValidator
July 3, 2023
Django 4.2.3 fixes a security issue with severity "moderate" and several bugs in 4.2.2.
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.
Fixed a regression in Django 4.2 that caused incorrect alignment of timezone
warnings for DateField and TimeField in the admin (:ticket:34645).
Fixed a regression in Django 4.2 that caused incorrect highlighting of rows
in the admin changelist view when ModelAdmin.list_editable contained a
BooleanField (:ticket:34638).
Django 4.2.2 fixes several bugs in 4.2.1.
June 5, 2023
Django 4.2.2 fixes several bugs in 4.2.1.
Fixed a regression in Django 4.2 that caused an unnecessary DBMS_LOB.SUBSTR() wrapping in the __isnull and __exact=None lookups for TextField()/BinaryField() on Oracle (34544).
Restored, following a regression in Django 4.2, get_prep_value() call in JSONField subclasses (34539).
Fixed a regression in Django 4.2 that caused a crash of QuerySet.defer() when passing a ManyToManyField or GenericForeignKey reference. While doing so is a no-op, it was allowed in older version (34570).
Fixed a regression in Django 4.2 that caused a crash of QuerySet.only() when passing a reverse OneToOneField reference (34612).
Fixed a bug in Django 4.2 where makemigrations --update didn't respect the --name option (34568).
Fixed a performance regression in Django 4.2 when compiling queries without ordering (34580).
Fixed a regression in Django 4.2 where nonexistent stylesheet was linked on a “Congratulations!” page (34588).
Fixed a regression in Django 4.2 that caused a crash of QuerySet.aggregate() with expressions referencing other aggregates (34551).
Fixed a regression in Django 4.2 that caused a crash of QuerySet.aggregate() with aggregates referencing subqueries (34551).
Fixed a regression in Django 4.2 that caused a crash of querysets on SQLite when filtering on DecimalField against values outside of the defined range (34590).
Fixed a regression in Django 4.2 that caused a serialization crash on a ManyToManyField without a natural key when its Manager’s base QuerySet used select_related() (34620).
CVE-2023-31047: Potential bypass of validation when uploading multiple files using one form field
May 3, 2023
Django 4.2.1 fixes a security issue with severity "low" and several bugs in 4.2.
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.
Fixed a regression in Django 4.2 that caused a crash of QuerySet.defer() when deferring fields by attribute names (34458).
Fixed a regression in Django 4.2 that caused a crash of ~django.contrib.postgres.search.SearchVector function with % characters (34459).
Fixed a regression in Django 4.2 that caused aggregation over query that uses explicit grouping to group against the wrong columns (34464).
Reallowed, following a regression in Django 4.2, setting the "cursor_factory" option in OPTIONS on PostgreSQL (34466).
Enforced UTF-8 client encoding on PostgreSQL, following a regression in Django 4.2 (34470).
Fixed a regression in Django 4.2 where i18n_patterns() didn't respect the prefix_default_language argument when a fallback language of the default language was used (34455).
Fixed a regression in Django 4.2 where translated URLs of the default language from i18n_patterns() with prefix_default_language set to False raised 404 errors for a request with a different language (34515).
Fixed a regression in Django 4.2 where creating copies and deep copies of HttpRequest, HttpResponse, and their subclasses didn't always work correctly (34482, 34484).
Fixed a regression in Django 4.2 where timesince and timeuntil template filters returned incorrect results for a datetime with a non-UTC timezone when a time difference is less than 1 day (34483).
Fixed a regression in Django 4.2 that caused a crash of ~django.contrib.postgres.search.SearchHeadline function with psycopg 3 (34486).
Fixed a regression in Django 4.2 that caused incorrect ClearableFileInput margins in the admin (34506).
Fixed a regression in Django 4.2 where breadcrumbs didn't appear on admin site app index views (34512).
Made squashing migrations reduce AddIndex, RemoveIndex, RenameIndex, and CreateModel operations which allows removing a deprecated Meta.index_together option from historical migrations and use Meta.indexes instead (34525).
- Django 4.2.30 release notes - Django 4.2.29 release notes - Django 4.2.28 release notes - Django 4.2.27 release notes - Django 4.2.26 release notes
Django 4.2.30 release notes
Django 4.2.29 release notes
Django 4.2.28 release notes
Django 4.2.27 release notes
Django 4.2.26 release notes
Django 4.2.25 release notes
Django 4.2.24 release notes
Django 4.2.23 release notes
Django 4.2.22 release notes
Django 4.2.21 release notes
Django 4.2.20 release notes
Django 4.2.19 release notes
Django 4.2.18 release notes
Django 4.2.17 release notes
Django 4.2.16 release notes
Django 4.2.15 release notes
Django 4.2.14 release notes
Django 4.2.13 release notes
Django 4.2.12 release notes
Django 4.2.11 release notes
Django 4.2.10 release notes
Django 4.2.9 release notes
Django 4.2.8 release notes
Django 4.2.7 release notes
Django 4.2.6 release notes
Django 4.2.5 release notes
Django 4.2.4 release notes
Django 4.2.3 release notes
Django 4.2.2 release notes
Django 4.2.1 release notes
Django 4.2 release notes
April 3, 2023
Welcome to Django 4.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 4.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 4.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 3.2, will end in April 2024.
Django 4.2 supports Python 3.8, 3.9, 3.10, 3.11, and 3.12 (as of 4.2.8). We highly recommend and only officially support the latest release of each series.
Django now supports psycopg version 3.1.8 or higher. To update your code, install the psycopg library, you don't need to change the ENGINE as django.db.backends.postgresql supports both libraries.
Support for psycopg2 is likely to be deprecated and removed at some point in the future.
Be aware that psycopg 3 introduces some breaking changes over psycopg2. As a consequence, you may need to make some changes to account for differences from psycopg2.
The new Field.db_comment and Meta.db_table_comment options allow creating comments on columns and tables, respectively. For example:
from django.db import models
class Question(models.Model):
text = models.TextField(db_comment="Poll question")
pub_date = models.DateTimeField(
db_comment="Date and time when the question was published",
)
class Meta:
db_table_comment = "Poll questions"
class Answer(models.Model):
question = models.ForeignKey(
Question,
on_delete=models.CASCADE,
db_comment="Reference to a question",
)
answer = models.TextField(db_comment="Question answer")
class Meta:
db_table_comment = "Question answers"
Also, the new ~django.db.migrations.operations.AlterModelTableComment operation allows changing table comments defined in the Meta.db_table_comment.
~django.middleware.gzip.GZipMiddleware now includes a mitigation for the BREACH attack. It will add up to 100 random bytes to gzip responses to make BREACH attacks harder. Read more about the mitigation technique in the Heal The Breach (HTB) paper.
The new django.core.files.storage.InMemoryStorage class provides a non-persistent storage useful for speeding up tests by avoiding disk access.
The new STORAGES setting allows configuring multiple custom file storage backends. It also controls storage engines for managing files (the "default" key) and static files (the "staticfiles" key).
The old DEFAULT_FILE_STORAGE and STATICFILES_STORAGE settings are deprecated as of this release.
The light or dark color theme of the admin can now be toggled in the UI, as well as being set to follow the system setting.
The admin's font stack now prefers system UI fonts and no longer requires downloading fonts. Additionally, CSS variables are available to more easily override the default font families.
The admin/delete_confirmation.html template now has some additional blocks and scripting hooks to ease customization.
The chosen options of ~django.contrib.admin.ModelAdmin.filter_horizontal and ~django.contrib.admin.ModelAdmin.filter_vertical widgets are now filterable.
The admin/base.html template now has a new block nav-breadcrumbs which contains the navigation landmark and the breadcrumbs block.
.ModelAdmin.list_editable now uses atomic transactions when making edits.
jQuery is upgraded from version 3.6.0 to 3.6.4.
The default iteration count for the PBKDF2 password hasher is increased from 390,000 to 600,000.
~django.contrib.auth.forms.UserCreationForm now saves many-to-many form fields for a custom user model.
The new ~django.contrib.auth.forms.BaseUserCreationForm is now the recommended base class for customizing the user creation form.
The GeoJSON serializer now outputs the id key for serialized features, which defaults to the primary key of objects.
The ~django.contrib.gis.gdal.GDALRaster class now supports pathlib.Path.
The ~django.contrib.gis.geoip2.GeoIP2 class now supports .mmdb files downloaded from DB-IP.
The OpenLayers template widget no longer includes inline CSS (which also removes the former map_css block) to better comply with a strict Content Security Policy.
~django.contrib.gis.forms.widgets.OpenLayersWidget is now based on OpenLayers 7.2.2 (previously 4.6.5).
The new isempty lookup and IsEmpty() expression allow filtering empty geometries on PostGIS.
The new FromWKB() and FromWKT() functions allow creating geometries from Well-known binary (WKB) and Well-known text (WKT) representations.
The new trigram_strict_word_similar lookup, and the TrigramStrictWordSimilarity() and TrigramStrictWordDistance() expressions allow using trigram strict word similarity.
The arrayfield.overlap lookup now supports QuerySet.values() and values_list() as a right-hand side.
The new .Sitemap.get_languages_for_item method allows customizing the list of languages for which the item is displayed.
~django.contrib.staticfiles.storage.ManifestStaticFilesStorage now has experimental support for replacing paths to JavaScript modules in import and export statements with their hashed counterparts. If you want to try it, subclass ManifestStaticFilesStorage and set the support_js_module_import_aggregation attribute to True.
The new .ManifestStaticFilesStorage.manifest_hash attribute provides a hash over all files in the manifest and changes whenever one of the files changes.
The new "assume_role" option is now supported in OPTIONS on PostgreSQL to allow specifying the session role.
The new "server_side_binding" option is now supported in OPTIONS on PostgreSQL with psycopg 3.1.8+ to allow using server-side binding cursors.
The debug page now shows exception notes and fine-grained error locations on Python 3.11+.
Session cookies are now treated as credentials and therefore hidden and replaced with stars (**********) in error reports.
~django.forms.ModelForm now accepts the new Meta option formfield_callback to customize form fields.
~django.forms.models.modelform_factory now respects the formfield_callback attribute of the form’s Meta.
Added support and translations for the Central Kurdish (Sorani) language.
The django-db-logger logger now logs transaction management queries (BEGIN, COMMIT, and ROLLBACK) at the DEBUG level.
makemessages command now supports locales with private sub-tags such as nl_NL-x-informal.
The new makemigrations --update option merges model changes into the latest migration and optimizes the resulting operations.
Migrations now support serialization of enum.Flag objects.
QuerySet now extensively supports filtering against window-functions with the exception of disjunctive filter lookups against window functions when performing aggregation.
~.QuerySet.prefetch_related now supports ~django.db.models.Prefetch objects with sliced querysets.
Registering lookups on ~django.db.models.Field instances is now supported.
The new robust argument for ~django.db.transaction.on_commit allows performing actions that can fail after a database transaction is successfully committed.
The new KT() expression represents the text value of a key, index, or path transform of ~django.db.models.JSONField.
~django.db.models.functions.Now now supports microsecond precision on MySQL and millisecond precision on SQLite.
F() expressions that output BooleanField can now be negated using ~F() (inversion operator).
Model now provides asynchronous versions of some methods that use the database, using an a prefix: ~.Model.adelete, ~.Model.arefresh_from_db, and ~.Model.asave.
Related managers now provide asynchronous versions of methods that change a set of related objects, using an a prefix: ~.RelatedManager.aadd, ~.RelatedManager.aclear, ~.RelatedManager.aremove, and ~.RelatedManager.aset.
CharField.max_length is no longer required to be set on PostgreSQL, which supports unlimited VARCHAR columns.
~django.http.StreamingHttpResponse now supports async iterators when Django is served via ASGI.
The test --debug-sql option now formats SQL queries with sqlparse.
The ~django.test.RequestFactory, ~django.test.AsyncRequestFactory, ~django.test.Client, and ~django.test.AsyncClient classes now support the headers parameter, which accepts a dictionary of header names and values. This allows a more natural syntax for declaring headers.
# Before:
self.client.get("/home/", HTTP_ACCEPT_LANGUAGE="fr")
await self.async_client.get("/home/", ACCEPT_LANGUAGE="fr")
# After:
self.client.get("/home/", headers={"accept-language": "fr"})
await self.async_client.get("/home/", headers={"accept-language": "fr"})
The new encoder parameter for django.utils.html.json_script function allows customizing a JSON encoder class.
The private internal vendored copy of urllib.parse.urlsplit() now strips '\r', '\n', and '\t' (see 2022-0391 and 43882). This is to protect projects that may be incorrectly using the internal url_has_allowed_host_and_scheme() function, instead of using one of the documented functions for handling URL redirects. The Django functions were not affected.
The new django.utils.http.content_disposition_header function returns a Content-Disposition HTTP header value as specified by 6266.
The list of common passwords used by CommonPasswordValidator is updated to the most recent version.
This section describes changes that may be needed in third-party database backends.
DatabaseFeatures.allows_group_by_pk is removed as it only remained to accommodate a MySQL extension that has been supplanted by proper functional dependency detection in MySQL 5.7.15. Note that DatabaseFeatures.allows_group_by_selected_pks is still supported and should be enabled if your backend supports functional dependency detection in GROUP BY clauses as specified by the SQL:1999 standard.
inspectdb now uses display_size from DatabaseIntrospection.get_table_description() rather than internal_size for CharField.
Upstream support for MariaDB 10.3 ends in May 2023. Django 4.2 supports MariaDB 10.4 and higher.
Upstream support for MySQL 5.7 ends in October 2023. Django 4.2 supports MySQL 8 and higher.
Upstream support for PostgreSQL 11 ends in November 2023. Django 4.2 supports PostgreSQL 12 and higher.
In order to avoid updating unnecessary columns, .QuerySet.update_or_create now passes update_fields to the Model.save() calls. As a consequence, any fields modified in the custom save() methods should be added to the update_fields keyword argument before calling super(). See overriding-model-methods for more details.
MySQL 8+ allows functional dependencies on GROUP BY columns, so the pre-Django 4.2 workaround of grouping by primary keys of the main table is removed. As a consequence, using RawSQL() aggregations is no longer supported on MySQL as there is no way to determine if such aggregations are needed or valid in the GROUP BY clause. Use aggregation-functions instead.
The undocumented django.http.multipartparser.parse_header() function is removed. Use django.utils.http.parse_header_parameters() instead.
{% blocktranslate asvar … %} result is now marked as safe for (HTML) output purposes.
The autofocus HTML attribute in the admin search box is removed as it can be confusing for screen readers.
The makemigrations --check option no longer creates missing migration files.
The alias argument for .Expression.get_group_by_cols is removed.
The minimum supported version of sqlparse is increased from 0.2.2 to 0.3.1.
The undocumented negated parameter of the ~django.db.models.Exists expression is removed.
The is_summary argument of the undocumented Query.add_annotation() method is removed.
The minimum supported version of SQLite is increased from 3.9.0 to 3.21.0.
The minimum supported version of asgiref is increased from 3.5.2 to 3.6.0.
~django.contrib.auth.forms.UserCreationForm now rejects usernames that differ only in case. If you need the previous behavior, use ~django.contrib.auth.forms.BaseUserCreationForm instead.
The minimum supported version of mysqlclient is increased from 1.4.0 to 1.4.3.
The minimum supported version of argon2-cffi is increased from 19.1.0 to 19.2.0.
The minimum supported version of Pillow is increased from 6.2.0 to 6.2.1.
The minimum supported version of jinja2 is increased from 2.9.2 to 2.11.0.
The minimum supported version of redis-py is increased from 3.0.0 to 3.4.0.
Manually instantiated WSGIRequest objects must be provided a file-like object for wsgi.input. Previously, Django was more lax than the expected behavior as specified by the WSGI specification.
Support for PROJ < 5 is removed.
SMTP EmailBackend now verifies a hostname and certificates. If you need the previous behavior that is less restrictive and not recommended, subclass EmailBackend and override the ssl_context property.
The Meta.index_together option is deprecated in favor of the ~django.db.models.Options.indexes option.
Migrating existing index_together should be handled as a migration. For example:
class Author(models.Model):
rank = models.IntegerField()
name = models.CharField(max_length=30)
class Meta:
index_together = [["rank", "name"]]
Should become:
class Author(models.Model):
rank = models.IntegerField()
name = models.CharField(max_length=30)
class Meta:
indexes = [models.Index(fields=["rank", "name"])]
Running the makemigrations command will generate a migration containing a ~django.db.migrations.operations.RenameIndex operation which will rename the existing index. Next, consider squashing migrations to remove index_together from historical migrations.
The AlterIndexTogether migration operation is now officially supported only for pre-Django 4.2 migration files. For backward compatibility reasons, it's still part of the public API, and there's no plan to deprecate or remove it, but it should not be used for new migrations. Use ~django.db.migrations.operations.AddIndex and ~django.db.migrations.operations.RemoveIndex operations instead.
JSONField and its associated lookups and aggregates used to allow passing JSON encoded string literals which caused ambiguity on whether string literals were already encoded from database backend's perspective.
During the deprecation period string literals will be attempted to be JSON decoded and a warning will be emitted on success that points at passing non-encoded forms instead.
Code that used to pass JSON encoded string literals:
Document.objects.bulk_create(
Document(data=Value("null")),
Document(data=Value("[]")),
Document(data=Value('"foo-bar"')),
)
Document.objects.annotate(
JSONBAgg("field", default=Value("[]")),
)
Should become:
Document.objects.bulk_create(
Document(data=Value(None, JSONField())),
Document(data=[]),
Document(data="foo-bar"),
)
Document.objects.annotate(
JSONBAgg("field", default=[]),
)
From Django 5.1+ string literals will be implicitly interpreted as JSON string literals.
The BaseUserManager.make_random_password() method is deprecated. See recipes and best practices for using Python's secrets module to generate passwords.
The length_is template filter is deprecated in favor of length and the == operator within an {% if %} tag. For example
{% if value|length == 4 %}…{% endif %}
{% if value|length == 4 %}True{% else %}False{% endif %}
instead of:
{% if value|length_is:4 %}…{% endif %}
{{ value|length_is:4 }}
django.contrib.auth.hashers.SHA1PasswordHasher, django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher, and django.contrib.auth.hashers.UnsaltedMD5PasswordHasher are deprecated.
django.contrib.postgres.fields.CICharField is deprecated in favor of CharField(db_collation="…") with a case-insensitive non-deterministic collation.
django.contrib.postgres.fields.CIEmailField is deprecated in favor of EmailField(db_collation="…") with a case-insensitive non-deterministic collation.
django.contrib.postgres.fields.CITextField is deprecated in favor of TextField(db_collation="…") with a case-insensitive non-deterministic collation.
django.contrib.postgres.fields.CIText mixin is deprecated.
The map_height and map_width attributes of BaseGeometryWidget are deprecated, use CSS to size map widgets instead.
SimpleTestCase.assertFormsetError() is deprecated in favor of assertFormSetError().
TransactionTestCase.assertQuerysetEqual() is deprecated in favor of assertQuerySetEqual().
Passing positional arguments to Signer and TimestampSigner is deprecated in favor of keyword-only arguments.
The DEFAULT_FILE_STORAGE setting is deprecated in favor of STORAGES["default"].
The STATICFILES_STORAGE setting is deprecated in favor of STORAGES["staticfiles"].
The django.core.files.storage.get_storage_class() function is deprecated.
Nothing published for this version
Nothing published for this version
Nothing published for this version
CVE-2023-46695: Potential denial of service vulnerability in UsernameField on Windows
November 1, 2023
Django 4.1.13 fixes a security issue with severity "moderate" in 4.1.12.
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 4.1.12 fixes a security issue with severity "moderate" in 4.1.11.
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 4.1.11 fixes a security issue with severity "moderate" in 4.1.10.
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 4.1.10 fixes a security issue with severity "moderate" in 4.1.9.
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 4.1.9 fixes a security issue with severity "low" in 4.1.8.
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.
Django 4.1.8 fixes a bug in 4.1.7.
April 5, 2023
Django 4.1.8 fixes a bug in 4.1.7.
SECRET_KEY_FALLBACKS (:ticket:34384).CVE-2023-24580: Potential denial-of-service vulnerability in file uploads
February 14, 2023
Django 4.1.7 fixes a security issue with severity "moderate" and a bug in 4.1.6.
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.
ValidationError with no code (:ticket:34319).CVE-2023-23969: Potential denial-of-service via Accept-Language headers
February 1, 2023
Django 4.1.6 fixes a security issue with severity "moderate" and a bug in 4.1.5.
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.
UniqueConstraint with ordered expressions (:ticket:34291).Django 4.1.5 fixes a bug in 4.1.4. Also, the latest string translations from Transifex are incorporated.
January 2, 2023
Django 4.1.5 fixes a bug in 4.1.4. Also, the latest string translations from Transifex are incorporated.
Fixed a long standing bug in the __len lookup for ArrayField that caused a crash of model validation on Meta.constraints (34205).
Django 4.1.4 fixes several bugs in 4.1.3.
December 6, 2022
Django 4.1.4 fixes several bugs in 4.1.3.
Fixed a regression in Django 4.1 that caused an unnecessary table rebuild when adding a ManyToManyField on SQLite (34138).
Fixed a bug in Django 4.1 that caused a crash of the sitemap index view with an empty Sitemap.items() and a callable ~django.contrib.sitemaps.Sitemap.lastmod (34088).
Fixed a bug in Django 4.1 that caused a crash using acreate(), aget_or_create(), and aupdate_or_create() asynchronous methods of related managers (34139).
Fixed a bug in Django 4.1 that caused a crash of QuerySet.bulk_create() with "pk" in unique_fields (34177).
Fixed a bug in Django 4.1 that caused a crash of QuerySet.bulk_create() on fields with db_column (34171).
Django 4.1.3 fixes a bug in 4.1.2 and adds compatibility with Python 3.11.
November 1, 2022
Django 4.1.3 fixes a bug in 4.1.2 and adds compatibility with Python 3.11.
startproject and startapp management commands from custom templates
to be incorrectly formatted using the black command (:ticket:34085).Your coding agent can read these notes before it upgrades. Set up the MCP server →