#27002: Redundant database query rendering a ModelChoiceField with RadioSelect
or
CheckboxSelectMultiple
----------------------------+--------------------
Reporter: AlexHill | Owner: nobody
Type: Bug | Status: new
Component: Forms | Version: 1.10
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------+--------------------
Followup to #27001:
Rendering a ModelChoiceField with RadioSelect and CheckboxSelectMultiple,
there's a redundant iteration that triggers an unnecessary database call.
Here's the relevant code from ForNode.render
([https://github.com/django/django/blob/ccd5a23fba91e66656bb19b60bb6d737cab728f5/django/template/defaulttags.py#L164
GitHub link]):
{{{#!python
if not hasattr(values, '__len__'): # line 164
values = list(values)
len_values = len(values)
...
for i, item in enumerate(values): # line 177
...
}}}
In this code, `values` is a BoundField. BoundField defines \__len__ like
this:
{{{#!python
def __len__(self):
return len(list(self.__iter__()))
}}}
So `len(values)` on line 164 triggers an iteration over `values` (and thus
a database query), then the for loop at line 177 triggers another.
The options as I see them are
1. Remove `BoundField.__len__` so that `list(values)` is called in
`ForNode.render`. This fixes the problem without breaking any tests. It is
backwards-incompatible (e.g. with an existing template passing a
boundfield to the `length` template filter), but not with anything
documented.
2. Cache iterator results somewhere internally so that the actual query is
only executed once. This is easy to do on BoundField with a cached
property. No backward compatibility concerns here.
3. Unconditionally call `list(values)` in ForNode. Also works, but a bit
heavy-handed and not necessary if one of the first two options are
acceptable.
I think (2) is the best choice. It's pretty clean, and it means the fix
can be implemented in 1.10 (and 1.8 LTS?) as a bug fix without backward
compatibility concerns.
--
Ticket URL: <https://code.djangoproject.com/ticket/27002>
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 post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.e33d244f20020c2d5fee6df85ec740f5%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.