[Django] #26166: Accessing a widget via an index on a BoundField results in unnecessary iteration

6 views
Skip to first unread message

Django

unread,
Feb 2, 2016, 7:30:39 AM2/2/16
to django-...@googlegroups.com
#26166: Accessing a widget via an index on a BoundField results in unnecessary
iteration
--------------------------------------+-------------------------------
Reporter: seddonym | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Forms | Version: 1.9
Severity: Normal | Keywords: forms, boundfield
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
--------------------------------------+-------------------------------
If you access a widget via its index on a `BoundField`, the `BoundField`
will iterate over its entire set of widgets. This can cause large
unnecessary overheads if you are accessing all the widgets in this way on,
say, a `ModelChoiceField` with a large queryset, as subwidgets ''for the
entire queryset will be generated for each widget''.

This is related to this ticket:
https://code.djangoproject.com/ticket/22745, and the fix here:
https://github.com/django/django/commit/5e06fa1469180909c51c07151692412269e51ea3

The specific example where this caused problems for me was in a custom
filter that helped pass the associated instance along with its associated
checkbox widget in the template.
(http://stackoverflow.com/a/27545910/1005499)

Example:

{{{
instance_widgets = []
index = 0
for instance in bound_field.field.queryset.all():
# Accessing the widget here will generate subwidgets for items in the
queryset
widget = copy(bound_field[index])
instance_widgets.append((instance, widget))
index += 1
}}}

If we store the instantiated subwidgets on the BoundField instance then we
reduce this overhead:

{{{
# django/forms/boundfield.py

...
class BoundField(object):
...
def __getitem__(self, idx):
if not isinstance(idx, six.integer_types):
raise TypeError
# Prevent unnecessary reevaluation when accessing BoundField's
attrs
# from templates.
if not hasattr(self, '_stored_subwidgets'):
self._stored_subwidgets = list(self.__iter__())
return self._stored_subwidgets[idx]
}}}

I'm not sure if this is necessarily the correct thing to do, but I thought
it worth reporting. An alternative would be just to give a warning if
widgets are being accessed in this way.

--
Ticket URL: <https://code.djangoproject.com/ticket/26166>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Feb 2, 2016, 12:27:07 PM2/2/16
to django-...@googlegroups.com
#26166: Accessing a widget via an index on a BoundField results in unnecessary
iteration
--------------------------------------+------------------------------------

Reporter: seddonym | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Forms | Version: 1.9
Severity: Normal | Resolution:
Keywords: forms, boundfield | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Changes (by timgraham):

* needs_better_patch: => 0
* needs_docs: => 0
* needs_tests: => 0
* stage: Unreviewed => Accepted


Comment:

I'm not sure about this either, but if we have a tested patch we can
evaluate it.

--
Ticket URL: <https://code.djangoproject.com/ticket/26166#comment:1>

Django

unread,
Jun 15, 2016, 10:53:47 AM6/15/16
to django-...@googlegroups.com
#26166: Accessing a widget via an index on a BoundField results in unnecessary
iteration
--------------------------------------+------------------------------------

Reporter: seddonym | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Forms | Version: 1.9
Severity: Normal | Resolution:
Keywords: forms, boundfield | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------

Comment (by bmispelon):

It might be worth it to effectively cache `BoundField.__iter__()` but in
your case, can't you use `zip` as a workaround:

{{{#!python
for widget, instance in zip(bound_field,
bound_field.field.queryset.all()):
instance_widgets.append((instance, copy(widget)))
}}}

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

Django

unread,
Aug 4, 2016, 11:22:56 AM8/4/16
to django-...@googlegroups.com
#26166: Accessing a widget via an index on a BoundField results in unnecessary
iteration
--------------------------------------+------------------------------------

Reporter: seddonym | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Forms | Version: 1.9
Severity: Normal | Resolution:
Keywords: forms, boundfield | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------

Comment (by timgraham):

Does the patch for #27002 solve this?

--
Ticket URL: <https://code.djangoproject.com/ticket/26166#comment:3>

Django

unread,
Sep 19, 2016, 2:29:13 PM9/19/16
to django-...@googlegroups.com
#26166: Accessing a widget via an index on a BoundField results in unnecessary
iteration
--------------------------------------+------------------------------------
Reporter: seddonym | Owner: nobody
Type: Cleanup/optimization | Status: closed
Component: Forms | Version: 1.9
Severity: Normal | Resolution: fixed

Keywords: forms, boundfield | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
--------------------------------------+------------------------------------
Changes (by timgraham):

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


Comment:

Please reopen if not.

--
Ticket URL: <https://code.djangoproject.com/ticket/26166#comment:4>

Reply all
Reply to author
Forward
0 new messages