#34925: refresh_from_db() will not iterate through all of the fields listed in
the
'fields' parameter.
-------------------------------------+-------------------------------------
Reporter: Andrew | Owner: nobody
Cordery |
Type: Bug | Status: new
Component: Database | Version: 4.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 1
UI/UX: 0 |
-------------------------------------+-------------------------------------
This one was killing me today. If you pass the 'fields' parameter to
{{{refresh_from_db}}} it is supposed to only remove those fields from
{{{_prefetched_objects_cache}}} as described in the docs:
https://docs.djangoproject.com/en/4.2/ref/models/instances/#django.db.models.Model.refresh_from_db.
Unfortunately, it modifies the 'fields' variable as it iterates through
it:
''Line 694 of django.db.models.base.py:''
{{{
for field in fields:
if field in prefetched_objects_cache:
del prefetched_objects_cache[field]
fields.remove(field)
}}}
Modifying the list that we are iterating over causes some list items to be
skipped. For example here we would expected to see 'a', 'b', and 'c',
removed from dict {{{d}}} but 'b' is skipped:
{{{
In [8]: d = dict(a=1,b=2, c=3)
In [9]: fields = ['a','b','c']
In [10]: for f in fields:
...: print(f)
...: if f in d:
...: del d[f]
...: fields.remove(f)
...:
a
c
In [11]: fields
Out[11]: ['b']
In [12]: d
Out[12]: {'b': 2}
}}}
I beieve that all that needs to be done to correct this is to create a
copy of the list by wrapping fields in list(), like so:
{{{
In [13]: fields = ['a','b','c']
In [14]: d=dict(a=1,b=2, c=3)
In [15]: for f in list(fields):
...: print(f)
...: if f in d:
...: del d[f]
...: fields.remove(f)
...:
a
b
c
In [16]: d
Out[16]: {}
In [17]: fields
Out[17]: []
}}}
Therefore as far as I can tell the fix to the django code would be as easy
as wrapping fields in list():
''Line 694 of django.db.models.base.py:'' modified
{{{
for field in list(fields):
if field in prefetched_objects_cache:
del prefetched_objects_cache[field]
fields.remove(field)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34925>
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/0107018b626f0809-ba4b776b-7246-44df-a5a9-c220ae15402f-000000%40eu-central-1.amazonses.com.