Skip to content

Commit

Permalink
Fixed #35238 -- Fixed database serialization crash when base managers…
Browse files Browse the repository at this point in the history
… use prefetch_related().

Regression in 1391356
following deprecation in eedbf930287cb72e9afab1f7208c24b1146b0c4ec.
  • Loading branch information
AlexCLeduc authored and felixxm committed Feb 20, 2024
1 parent eb2d49b commit a084c5d
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 1 deletion.
5 changes: 4 additions & 1 deletion django/db/backends/base/creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,10 @@ def get_objects():
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()
Expand Down
4 changes: 4 additions & 0 deletions docs/releases/5.0.3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
17 changes: 17 additions & 0 deletions tests/backends/base/test_creation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
Object,
ObjectReference,
ObjectSelfReference,
SchoolBus,
SchoolClass,
)

Expand Down Expand Up @@ -250,6 +251,22 @@ def test_serialize_db_to_string_base_manager(self):
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):
Expand Down
14 changes: 14 additions & 0 deletions tests/backends/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a084c5d

Please sign in to comment.