[Django] #37027: refresh_from_db() with from_queryset + prefetch does not persist result in instance

4 views
Skip to first unread message

Django

unread,
Apr 9, 2026, 8:51:57 AM (yesterday) Apr 9
to django-...@googlegroups.com
#37027: refresh_from_db() with from_queryset + prefetch does not persist result in
instance
-------------------------------------+-------------------------------------
Reporter: Hugo Maingonnat | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | Severity: Normal
Keywords: refresh_from_db, | Triage Stage:
prefetch | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
{{{
foo = Foo.objects.create(**data)
# The prefetch query is executed, but does not seem to be persisted into
the instance
prefetch = Prefetch('bar_set', queryset=Bar.objects.all())
foo.refresh_from_db(from_queryset=Foo.objects.prefetch_related(
prefetch
))
# This is empty
print('CACHE:', foo._prefetched_objects_cache)
# Lazy extra query is executed because prefetch was not persisted: this
should not happen
list(foo.bar_set.all())
}}}

This also does not work if for example `to_attr='bar_list'` is set in the
prefetch, then `foo.bar_list` is not set.

Note that using `select_related()` is working.
--
Ticket URL: <https://code.djangoproject.com/ticket/37027>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Apr 9, 2026, 9:24:58 AM (yesterday) Apr 9
to django-...@googlegroups.com
#37027: refresh_from_db() with from_queryset + prefetch does not persist result in
instance
-------------------------------------+-------------------------------------
Reporter: Hugo Maingonnat | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: refresh_from_db, | Triage Stage:
prefetch | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Simon Charette):

There's is little value in using `prefetch_related` when dealing with a
single object as this method is meant to be used to prevent N+1 query
issues but in this case `N=1` so the number of queries will be the same.
In other words, performing `foo.bar_set.all()` will issue the same query
as what a prefetching would have done.

When we added `refresh_from_db(from_queryset)` support (#28344) we knew it
would open the door to a large surface area between `Model` and `QuerySet`
APIs. Given the original intent was to support `for_update` and friends
I'm not convinced we should add support for `prefetch_related` and
certainly not for `Prefetch(to_attr)` as it doesn't follow the
`refresh_from_db(fields)` convention.

Support for `select_related` came for free as it's a normal attribute
lookup on the retrieved model instance and there are real benefits to
using it (reducing the number of queries). In the case of
`prefetch_related` it requires extra retrieval and invalidation logic of
many-to-many relationships and results in the same number of queries.
--
Ticket URL: <https://code.djangoproject.com/ticket/37027#comment:1>

Django

unread,
Apr 9, 2026, 1:15:53 PM (yesterday) Apr 9
to django-...@googlegroups.com
#37027: refresh_from_db() with from_queryset + prefetch does not persist result in
instance
-------------------------------------+-------------------------------------
Reporter: Hugo Maingonnat | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: refresh_from_db, | Triage Stage:
prefetch | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by MANAS MADESHIYA):

* cc: MANAS MADESHIYA (added)

--
Ticket URL: <https://code.djangoproject.com/ticket/37027#comment:2>

Django

unread,
5:23 PM (2 hours ago) 5:23 PM
to django-...@googlegroups.com
#37027: refresh_from_db() with from_queryset + prefetch does not persist result in
instance
-------------------------------------+-------------------------------------
Reporter: Hugo Maingonnat | Owner: (none)
Type: Bug | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: wontfix
Keywords: refresh_from_db, | Triage Stage:
prefetch | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* resolution: => wontfix
* status: new => closed

Comment:

Simon's doubts are convincing. If helpful, I'll add that I had a need for
this in a project (I had a tree of objects shaped via custom
`Prefetch(to_attr=...)` that I needed to be able to refresh), and I found
an involved workaround. Thanks to your ticket, I had the idea to retry
after #28455 (Django 6.1), and there's now a much simpler workaround.

Just prevent the `from_queryset` from being cloned, and then the prefetch
result is still accessible to you, and in your override of
`Model.refresh_from_db` you can put it where you expect it.

{{{#!py
In [1]: admin = User.objects.get(username='admin')

In [2]: reset_queries()

In [3]: from_queryset = User.objects.prefetch_related("groups")

In [4]: with from_queryset._avoid_cloning():
...: admin.refresh_from_db(from_queryset=from_queryset)
...:

In [5]: from_queryset[0]._prefetched_objects_cache
Out[5]: {'groups': <QuerySet [<Group: Graph Editor>, <Group: Resource
Editor>, <Group: RDM Administrator>, <Group: Application Administrator>,
<Group: System Administrator>, <Group: Mobile Project Administrator>,
<Group: Crowdsource Editor>, <Group: Guest>, <Group: Resource Reviewer>,
<Group: Resource Exporter>]>}

In [6]: connection.queries
Out[6]:
[{'sql': 'SELECT "auth_user"."id", "auth_user"."password",
"auth_user"."last_login", "auth_user"."is_superuser",
"auth_user"."username", "auth_user"."first_name", "auth_user"."last_name",
"auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active",
"auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1
LIMIT 21',
'time': '0.005'},
{'sql': 'SELECT ("auth_user_groups"."user_id") AS
"_prefetch_related_val_user_id", "auth_group"."id", "auth_group"."name"
FROM "auth_group" INNER JOIN "auth_user_groups" ON ("auth_group"."id" =
"auth_user_groups"."group_id") WHERE "auth_user_groups"."user_id" IN (1)',
'time': '0.004'}]
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/37027#comment:3>
Reply all
Reply to author
Forward
0 new messages