[4.1.x] Fixed #33952 -- Reallowed creating reverse foreign key managers on unsaved instances.

Thanks Claude Paroz for the report.

Regression in 7ba6ebe914.

Backport of 806e9e2d0d from main
This commit is contained in:
David Wobrock 2022-08-24 21:14:32 +02:00 committed by Mariusz Felisiak
parent 0890719402
commit fca055315e
3 changed files with 14 additions and 9 deletions

View File

@ -627,15 +627,6 @@ def create_reverse_many_to_one_manager(superclass, rel):
self.core_filters = {self.field.name: instance} self.core_filters = {self.field.name: instance}
# Even if this relation is not to pk, we require still pk value.
# The wish is that the instance has been already saved to DB,
# although having a pk value isn't a guarantee of that.
if self.instance.pk is None:
raise ValueError(
f"{instance.__class__.__name__!r} instance needs to have a primary "
f"key value before this relationship can be used."
)
def __call__(self, *, manager): def __call__(self, *, manager):
manager = getattr(self.model, manager) manager = getattr(self.model, manager)
manager_class = create_reverse_many_to_one_manager(manager.__class__, rel) manager_class = create_reverse_many_to_one_manager(manager.__class__, rel)
@ -700,6 +691,14 @@ def create_reverse_many_to_one_manager(superclass, rel):
pass # nothing to clear from cache pass # nothing to clear from cache
def get_queryset(self): def get_queryset(self):
# Even if this relation is not to pk, we require still pk value.
# The wish is that the instance has been already saved to DB,
# although having a pk value isn't a guarantee of that.
if self.instance.pk is None:
raise ValueError(
f"{self.instance.__class__.__name__!r} instance needs to have a "
f"primary key value before this relationship can be used."
)
try: try:
return self.instance._prefetched_objects_cache[ return self.instance._prefetched_objects_cache[
self.field.remote_field.get_cache_name() self.field.remote_field.get_cache_name()

View File

@ -49,3 +49,6 @@ Bugfixes
* Fixed a regression in Django 4.1 that caused an incorrect migration when * Fixed a regression in Django 4.1 that caused an incorrect migration when
renaming a model with ``ManyToManyField`` and ``db_table`` (:ticket:`33953`). renaming a model with ``ManyToManyField`` and ``db_table`` (:ticket:`33953`).
* Reallowed, following a regression in Django 4.1, creating reverse foreign key
managers on unsaved instances (:ticket:`33952`).

View File

@ -748,6 +748,9 @@ class ManyToOneTests(TestCase):
) )
with self.assertRaisesMessage(ValueError, msg): with self.assertRaisesMessage(ValueError, msg):
th.child_set.count() th.child_set.count()
# The reverse foreign key manager can be created.
self.assertEqual(th.child_set.model, Third)
th.save() th.save()
# Now the model is saved, so we will need to execute a query. # Now the model is saved, so we will need to execute a query.
with self.assertNumQueries(1): with self.assertNumQueries(1):