diff options
| author | Keryn Knight <keryn@kerynknight.com> | 2026-01-10 08:39:45 +0100 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2026-03-11 18:05:44 +0100 |
| commit | 804607df0e174c524a3ea880b8ecbb555ecb4abb (patch) | |
| tree | 8d602a76d9cdcbec2357a96588e68886bb3bd705 /django/db/models/fields | |
| parent | 8d8a8713432a88737c4400610eef11c5c8457b86 (diff) | |
Refs #28455 -- Avoided QuerySet cloning in simple prefetch_related() usages.
manager.get_queryset() always returns freshly instantiated per-instance
QuerySet which doesn't need subsequent cloning.
Based on work originally done by Anssi Kääriäinen and Tim Graham.
Diffstat (limited to 'django/db/models/fields')
| -rw-r--r-- | django/db/models/fields/related_descriptors.py | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/django/db/models/fields/related_descriptors.py b/django/db/models/fields/related_descriptors.py index 40ad8b260f..87b4921a6c 100644 --- a/django/db/models/fields/related_descriptors.py +++ b/django/db/models/fields/related_descriptors.py @@ -738,12 +738,13 @@ def create_reverse_many_to_one_manager(superclass, rel): empty_strings_as_null = connections[ db ].features.interprets_empty_strings_as_nulls - queryset._add_hints(instance=self.instance) - if self._db: - queryset = queryset.using(self._db) - queryset._fetch_mode = self.instance._state.fetch_mode - queryset._defer_next_filter = True - queryset = queryset.filter(**self.core_filters) + with queryset._avoid_cloning(): + queryset._add_hints(instance=self.instance) + if self._db: + queryset = queryset.using(self._db) + queryset._fetch_mode = self.instance._state.fetch_mode + queryset._defer_next_filter = True + queryset = queryset.filter(**self.core_filters) for field in self.field.foreign_related_fields: val = getattr(self.instance, field.attname) if val is None or (val == "" and empty_strings_as_null): @@ -1140,12 +1141,13 @@ def create_forward_many_to_many_manager(superclass, rel, reverse): """ Filter the queryset for the instance this manager is bound to. """ - queryset._add_hints(instance=self.instance) - if self._db: - queryset = queryset.using(self._db) - queryset._fetch_mode = self.instance._state.fetch_mode - queryset._defer_next_filter = True - return queryset._next_is_sticky().filter(**self.core_filters) + with queryset._avoid_cloning(): + queryset._add_hints(instance=self.instance) + if self._db: + queryset = queryset.using(self._db) + queryset._fetch_mode = self.instance._state.fetch_mode + queryset._defer_next_filter = True + return queryset._next_is_sticky().filter(**self.core_filters) def get_prefetch_cache(self): # Walk up the ancestor-chain (if cached) to try and find a prefetch |
