summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexCLeduc <ledualex@gmail.com>2024-02-19 17:36:04 -0500
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2024-02-21 05:17:36 +0100
commit69e5b13c758cec55edbab342da8be509557589f4 (patch)
tree3c1cd88f502e72028f2b0f3bd02f7d923ee5f21b
parente72fdc850a7c7703a5e019de127a4256bc136479 (diff)
[5.0.x] Fixed #35238 -- Fixed database serialization crash when base managers use prefetch_related().
Regression in 139135627650ed6aaaf4c755b82c3bd43f2b8f51 following deprecation in eedbf930287cb72e9afab1f7208c24b1146b0c4ec. Backport of a084c5d35a6d00abd261338a374a4424764b4aee from main
-rw-r--r--django/db/backends/base/creation.py5
-rw-r--r--docs/releases/5.0.3.txt4
-rw-r--r--tests/backends/base/test_creation.py17
-rw-r--r--tests/backends/models.py14
4 files changed, 39 insertions, 1 deletions
diff --git a/django/db/backends/base/creation.py b/django/db/backends/base/creation.py
index cbac8a7f76..6856fdb596 100644
--- a/django/db/backends/base/creation.py
+++ b/django/db/backends/base/creation.py
@@ -135,7 +135,10 @@ class BaseDatabaseCreation:
queryset = model._base_manager.using(
self.connection.alias,
).order_by(model._meta.pk.name)
- yield from queryset.iterator()
+ chunk_size = (
+ 2000 if queryset._prefetch_related_lookups else None
+ )
+ yield from queryset.iterator(chunk_size=chunk_size)
# Serialize to a string
out = StringIO()
diff --git a/docs/releases/5.0.3.txt b/docs/releases/5.0.3.txt
index e17fdd531f..297e17d023 100644
--- a/docs/releases/5.0.3.txt
+++ b/docs/releases/5.0.3.txt
@@ -24,3 +24,7 @@ Bugfixes
* 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 (:ticket:`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()``
+ (:ticket:`35238`).
diff --git a/tests/backends/base/test_creation.py b/tests/backends/base/test_creation.py
index 9593e13462..7e760e8884 100644
--- a/tests/backends/base/test_creation.py
+++ b/tests/backends/base/test_creation.py
@@ -14,6 +14,7 @@ from ..models import (
Object,
ObjectReference,
ObjectSelfReference,
+ SchoolBus,
SchoolClass,
)
@@ -250,6 +251,22 @@ class TestDeserializeDbFromString(TransactionTestCase):
self.assertIn('"model": "backends.schoolclass"', data)
self.assertIn('"year": 1000', data)
+ def test_serialize_db_to_string_base_manager_with_prefetch_related(self):
+ sclass = SchoolClass.objects.create(
+ year=2000, last_updated=datetime.datetime.now()
+ )
+ bus = SchoolBus.objects.create(number=1)
+ bus.schoolclasses.add(sclass)
+ with mock.patch("django.db.migrations.loader.MigrationLoader") as loader:
+ # serialize_db_to_string() serializes only migrated apps, so mark
+ # the backends app as migrated.
+ loader_instance = loader.return_value
+ loader_instance.migrated_apps = {"backends"}
+ data = connection.creation.serialize_db_to_string()
+ self.assertIn('"model": "backends.schoolbus"', data)
+ self.assertIn('"model": "backends.schoolclass"', data)
+ self.assertIn(f'"schoolclasses": [{sclass.pk}]', data)
+
class SkipTestClass:
def skip_function(self):
diff --git a/tests/backends/models.py b/tests/backends/models.py
index 99e9e86f44..1ed108c2b8 100644
--- a/tests/backends/models.py
+++ b/tests/backends/models.py
@@ -32,6 +32,20 @@ class SchoolClass(models.Model):
objects = SchoolClassManager()
+class SchoolBusManager(models.Manager):
+ def get_queryset(self):
+ return super().get_queryset().prefetch_related("schoolclasses")
+
+
+class SchoolBus(models.Model):
+ number = models.IntegerField()
+ schoolclasses = models.ManyToManyField("SchoolClass")
+ objects = SchoolBusManager()
+
+ class Meta:
+ base_manager_name = "objects"
+
+
class VeryLongModelNameZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ(models.Model):
primary_key_is_quite_long_zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz = models.AutoField(
primary_key=True