From afb8ad29924d5439b973f2d2653bb58ce577f8cf Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 1 Oct 2025 08:52:19 -0400 Subject: [PATCH 01/27] [5.2.x] Post-release version bump. --- django/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/django/__init__.py b/django/__init__.py index 4a73d1fec593..caa03e41eae9 100644 --- a/django/__init__.py +++ b/django/__init__.py @@ -1,6 +1,6 @@ from django.utils.version import get_version -VERSION = (5, 2, 7, "final", 0) +VERSION = (5, 2, 8, "alpha", 0) __version__ = get_version(VERSION) From f94449ef69b3846f02f0ad3964192711b32f9ef6 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 1 Oct 2025 10:30:45 -0400 Subject: [PATCH 02/27] [5.2.x] Added stub release notes for 5.2.8. Backport of 1324d9037e9281ec0fdd88c15b20881c7a6ea8b9 from main. --- docs/releases/5.2.8.txt | 13 +++++++++++++ docs/releases/index.txt | 1 + 2 files changed, 14 insertions(+) create mode 100644 docs/releases/5.2.8.txt diff --git a/docs/releases/5.2.8.txt b/docs/releases/5.2.8.txt new file mode 100644 index 000000000000..fd35dd6af53b --- /dev/null +++ b/docs/releases/5.2.8.txt @@ -0,0 +1,13 @@ +========================== +Django 5.2.8 release notes +========================== + +*Expected November 5, 2025* + +Django 5.2.8 fixes several bugs in 5.2.7. + +Bugfixes +======== + +* ... + diff --git a/docs/releases/index.txt b/docs/releases/index.txt index 02f2762be1f9..f8d69ac1db6f 100644 --- a/docs/releases/index.txt +++ b/docs/releases/index.txt @@ -25,6 +25,7 @@ versions of the documentation contain the release notes for any later releases. .. toctree:: :maxdepth: 1 + 5.2.8 5.2.7 5.2.6 5.2.5 From 071afc3d01d330ea48b79917a6227fff545d5620 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Wed, 1 Oct 2025 10:39:02 -0400 Subject: [PATCH 03/27] [5.2.x] Added CVE-2025-59681 and CVE-2025-59682 to security archive. Backport of 43d84aef04a9e71164c21a74885996981857e66e from main. --- docs/releases/security.txt | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/docs/releases/security.txt b/docs/releases/security.txt index df5571e374eb..78138060ba63 100644 --- a/docs/releases/security.txt +++ b/docs/releases/security.txt @@ -36,6 +36,30 @@ Issues under Django's security process All security issues have been handled under versions of Django's security process. These are listed below. +October 1, 2025 - :cve:`2025-59681` +----------------------------------- + +Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB. +`Full description +`__ + +* Django 6.0 :commit:`(patch) <4ceaaee7e04b416fc465e838a6ef43ca0ccffafe>` +* Django 5.2 :commit:`(patch) <52fbae0a4dbbe5faa59827f8f05694a0065cc135>` +* Django 5.1 :commit:`(patch) <01d2d770e22bffe53c7f1e611e2bbca94cb8a2e7>` +* Django 4.2 :commit:`(patch) <38d9ef8c7b5cb6ef51b933e51a20e0e0063f33d5>` + +October 1, 2025 - :cve:`2025-59682` +----------------------------------- + +Potential partial directory-traversal via ``archive.extract()``. +`Full description +`__ + +* Django 6.0 :commit:`(patch) ` +* Django 5.2 :commit:`(patch) ` +* Django 5.1 :commit:`(patch) <74fa85c688a87224637155902bcd738bb9e65e11>` +* Django 4.2 :commit:`(patch) <9504bbaa392c9fe37eee9291f5b4c29eb6037619>` + September 3, 2025 - :cve:`2025-57833` ------------------------------------- From 2fc538af33f455675ee9e61e5897f58609b6745c Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 1 Oct 2025 21:15:57 +0200 Subject: [PATCH 04/27] [5.2.x] Rewrapped security archive at 79 chars. Backport of 1499c95d990fb776c39ad60e43228cbbbfcad3a8 from main. --- docs/releases/security.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/releases/security.txt b/docs/releases/security.txt index 78138060ba63..ff4f1d37890e 100644 --- a/docs/releases/security.txt +++ b/docs/releases/security.txt @@ -39,8 +39,8 @@ process. These are listed below. October 1, 2025 - :cve:`2025-59681` ----------------------------------- -Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, ``aggregate()``, and ``extra()`` on MySQL and MariaDB. -`Full description +Potential SQL injection in ``QuerySet.annotate()``, ``alias()``, +``aggregate()``, and ``extra()`` on MySQL and MariaDB. `Full description `__ * Django 6.0 :commit:`(patch) <4ceaaee7e04b416fc465e838a6ef43ca0ccffafe>` From 41bcb54bff9c90b05201881c0850f4ef938e2b55 Mon Sep 17 00:00:00 2001 From: Jacob Walls Date: Thu, 25 Sep 2025 09:56:24 -0400 Subject: [PATCH 05/27] [5.2.x] Refs #36143, #28596 -- Avoided mentioning exact query parameter limit in bulk_create() docs. Backport of 0a09c60e97166e0188717ff340b4d93b72207e96 from main. --- docs/ref/models/querysets.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index 7c76daa824bb..df9da9b1c799 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -2449,8 +2449,8 @@ This has a number of caveats though: Entry.objects.bulk_create(batch, batch_size) The ``batch_size`` parameter controls how many objects are created in a single -query. The default is to create all objects in one batch, except for SQLite -where the default is such that at most 999 variables per query are used. +query. The default is to create as many objects in one batch as the database +will allow. (SQLite and Oracle limit the number of parameters in a query.) On databases that support it (all but Oracle), setting the ``ignore_conflicts`` parameter to ``True`` tells the database to ignore failure to insert any rows From 2d2e1a6a9dbfe0cba58a4d2486c51fccdb501d55 Mon Sep 17 00:00:00 2001 From: Dani Fornons Date: Fri, 3 Oct 2025 12:20:28 +0200 Subject: [PATCH 06/27] [5.2.x] Fixed #36636, Refs #15902 -- Removed session-based storage reference from set_language() docs. Backport of 2514857e3fae831106832cca8823237801cf2cad from main. --- django/views/i18n.py | 6 +++--- docs/topics/i18n/translation.txt | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/django/views/i18n.py b/django/views/i18n.py index 771035d8ab29..04e37e4ac170 100644 --- a/django/views/i18n.py +++ b/django/views/i18n.py @@ -29,9 +29,9 @@ def builtin_template_path(name): def set_language(request): """ - Redirect to a given URL while setting the chosen language in the session - (if enabled) and in a cookie. The URL and the language code need to be - specified in the request parameters. + Redirect to a given URL while setting the chosen language in the language + cookie. The URL and the language code need to be specified in the request + parameters. Since this view changes how the user will see the rest of the site, it must only be accessed as a POST request. If called as a GET request, it will diff --git a/docs/topics/i18n/translation.txt b/docs/topics/i18n/translation.txt index eacf2a323463..faeccbaecf09 100644 --- a/docs/topics/i18n/translation.txt +++ b/docs/topics/i18n/translation.txt @@ -1881,10 +1881,9 @@ Activate this view by adding the following line to your URLconf:: language-independent itself to work correctly. The view expects to be called via the ``POST`` method, with a ``language`` -parameter set in request. If session support is enabled, the view saves the -language choice in the user's session. It also saves the language choice in a -cookie that is named ``django_language`` by default. (The name can be changed -through the :setting:`LANGUAGE_COOKIE_NAME` setting.) +parameter set in request. The view saves the language choice in a cookie that +is named ``django_language`` by default. (The name can be changed through the +:setting:`LANGUAGE_COOKIE_NAME` setting.) After setting the language choice, Django looks for a ``next`` parameter in the ``POST`` or ``GET`` data. If that is found and Django considers it to be a safe From 084cbe1217a79230b7bc616a40e900baeb3a45d6 Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Wed, 8 Oct 2025 10:58:59 +0200 Subject: [PATCH 07/27] [5.2.x] Added missing backticks in docs/ref/models/fields.txt. Backport of 4a8ca8bd6906b705c4445bc915d71beda2fc4b84 from main --- docs/ref/models/fields.txt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 511b6e0215a9..de0b888f82da 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -1727,8 +1727,9 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in * .. attribute:: CASCADE - Cascade deletes. Django emulates the behavior of the SQL constraint ON - DELETE CASCADE and also deletes the object containing the ForeignKey. + Cascade deletes. Django emulates the behavior of the SQL constraint ``ON + DELETE CASCADE`` and also deletes the object containing the + :class:`ForeignKey`. :meth:`.Model.delete` isn't called on related models, but the :data:`~django.db.models.signals.pre_delete` and @@ -1947,9 +1948,9 @@ The possible values for :attr:`~ForeignKey.on_delete` are found in Setting it to ``False`` does not mean you can reference a swappable model even if it is swapped out - ``False`` means that the migrations made - with this ForeignKey will always reference the exact model you specify - (so it will fail hard if the user tries to run with a User model you don't - support, for example). + with this :class:`ForeignKey` will always reference the exact model you + specify (so it will fail hard if the user tries to run with a ``User`` + model you don't support, for example). If in doubt, leave it to its default of ``True``. From c05c5b80a6108f84f786da46ba5de3a4972b9b73 Mon Sep 17 00:00:00 2001 From: "Michiel W. Beijen" Date: Fri, 6 Dec 2024 20:54:41 +0100 Subject: [PATCH 08/27] [5.2.x] Fixed #35961 -- Migrated license metadata in pyproject.toml to conform PEP 639. See https://peps.python.org/pep-0639/ and https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license-and-license-files. Co-authored-by: Jacob Walls Backport of 96a7a652166bece8acc96d6335ebb8091de2f496 from main. --- docs/intro/reusable-apps.txt | 4 ++-- pyproject.toml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/intro/reusable-apps.txt b/docs/intro/reusable-apps.txt index 3ed336e62c98..b353cdc9bb86 100644 --- a/docs/intro/reusable-apps.txt +++ b/docs/intro/reusable-apps.txt @@ -209,7 +209,7 @@ this. For a small app like polls, this process isn't too difficult. :caption: ``django-polls/pyproject.toml`` [build-system] - requires = ["setuptools>=69.3"] + requires = ["setuptools>=77.0.3"] build-backend = "setuptools.build_meta" [project] @@ -220,6 +220,7 @@ this. For a small app like polls, this process isn't too difficult. ] description = "A Django app to conduct web-based polls." readme = "README.rst" + license = "BSD-3-Clause" requires-python = ">= 3.10" authors = [ {name = "Your Name", email = "yourname@example.com"}, @@ -229,7 +230,6 @@ this. For a small app like polls, this process isn't too difficult. "Framework :: Django", "Framework :: Django :: X.Y", # Replace "X.Y" as appropriate "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", diff --git a/pyproject.toml b/pyproject.toml index a2b438cf024c..3306ef9cef9a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools>=75.8.1"] +requires = ["setuptools>=77.0.3"] build-backend = "setuptools.build_meta" [project] @@ -16,13 +16,13 @@ authors = [ ] description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." readme = "README.rst" -license = {text = "BSD-3-Clause"} +license = "BSD-3-Clause" +license-files = ["LICENSE", "LICENSE.python"] classifiers = [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Intended Audience :: Developers", - "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", From 80b9c8f5292dfa38469a1e85314cc45b8374eb22 Mon Sep 17 00:00:00 2001 From: Natalia <124304+nessita@users.noreply.github.com> Date: Thu, 28 Aug 2025 17:19:20 -0300 Subject: [PATCH 09/27] [5.2.x] Fixed #36526 -- Doc'd QuerySet.bulk_update() memory usage when batching. Thanks Simon Charette for the review. Backport of 608d3ebc8889863d43be1090d634b9507fe4a85e from main. --- docs/ref/models/querysets.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index df9da9b1c799..f509e7d616a4 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -2510,6 +2510,21 @@ them, but it has a few caveats: * If updating a large number of columns in a large number of rows, the SQL generated can be very large. Avoid this by specifying a suitable ``batch_size``. +* When updating a large number of objects, be aware that ``bulk_update()`` + prepares all of the ``WHEN`` clauses for every object across all batches + before executing any queries. This can require more memory than expected. To + reduce memory usage, you can use an approach like this:: + + from itertools import islice + + batch_size = 100 + ids_iter = range(1000) + while ids := list(islice(ids_iter, batch_size)): + batch = Entry.objects.filter(ids__in=ids) + for entry in batch: + entry.headline = f"Updated headline {entry.pk}" + Entry.objects.bulk_update(batch, ["headline"], batch_size=batch_size) + * Updating fields defined on multi-table inheritance ancestors will incur an extra query per ancestor. * When an individual batch contains duplicates, only the first instance in that From 713e9d8f53c20a785e766477fa5270575833193e Mon Sep 17 00:00:00 2001 From: Mariusz Felisiak Date: Thu, 9 Oct 2025 20:01:31 +0200 Subject: [PATCH 10/27] [5.2.x] Corrected admin check IDs in docs. Backport of 1167cd1d639c3fee69dbdef351d31e8a17d1fedf from main --- docs/ref/checks.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index fd0983dfadcd..fe33990a22d2 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -814,11 +814,11 @@ The following checks are performed on any :class:`~django.contrib.contenttypes.admin.GenericInlineModelAdmin` that is registered as an inline on a :class:`~django.contrib.admin.ModelAdmin`. -* **admin.E301**: ``'ct_field'`` references ``