#33596: Subsequent calls to prefetch_related_objects() don't work for model
instances that have changed.
-------------------------------------+-------------------------------------
Reporter: Dennis Kliban | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 3.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Simon Charette):
I wonder if this is actually a bug or we should ''wontfix'' this one.
The definition of `is_fetched` for a prefetched relationship via `to_attr`
is the presence of the attribute itself. The
[https://github.com/django/django/blob/1b695fbbc203c163bf7b8d78f6313a6c506fb938/django/db/models/fields/related_descriptors.py#L735
many-to-many manager already takes care of clearing the prefetched objects
that Django knows about when add is called] (`_prefetched_objects_cache`
is under Django's control) but unless we introduce a way to do some
bookeeping of the form `_prefetched_to_attrs: dict[prefetch_cache_name:
str, to_attrs: list[str]]` when `to_attr` is used I don't see how we can
fix this issue.
Then comes the question of what to do if the property doesn't support
`del` and documenting that this change now breaks patterns of the form
{{{#!python
bookings = Booking.objects.prefetch_related(
'seats',
Prefetch('seats', to_attr='existing_seats'),
)
sync_bookings(bookings) # function that alters .seats one way or the
other
added_seats = []
removed_seats = []
for booking in bookings:
added_seats.extend(set(booking.seats.all()) -
set(booking.existing_seats))
removed_seats.extend(set(booking.existing_seats) -
set(booking.seats.all())
}}}
Since it's not obvious if `to_attr` should be cleared or not on a
prefetched relationship change and we've defaulting to not doing so since
the introduction of the feature I'd be inclined to ''wontfix'' this one
and declare that it's the user responsibility to clear `to_attr` fetched
relationships prior to attempting a second round of
`prefetch_related_objects` and do the book keeping themselves:
{{{#!diff
diff --git a/tests/prefetch_related/test_prefetch_related_objects.py
b/tests/prefetch_related/test_prefetch_related_objects.py
index 8be643e6dc..edd0bffe2f 100644
--- a/tests/prefetch_related/test_prefetch_related_objects.py
+++ b/tests/prefetch_related/test_prefetch_related_objects.py
@@ -151,6 +151,7 @@ def
test_prefetch_object_to_attr_twice_with_change(self):
)
self.assertCountEqual(book.the_authors, [])
book.authors.add(author)
+ del book.the_authors
with self.assertNumQueries(1):
prefetch_related_objects(
[book],
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/33596#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107017fbc5a248d-7370e447-7af0-4cc3-ae56-b0c806f4817b-000000%40eu-central-1.amazonses.com.