Opened 8 years ago

Closed 8 years ago

#3300 closed defect (fixed)

newforms Select widget only renders choices once when using generator

Reported by: m_fremont@… Owned by: adrian
Component: Forms Version: master
Severity: normal Keywords: newforms Select widget
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

The newforms Select widget (newforms.django.widgets.Select) only renders the select list choices on the first call when using a generator for the choices constructor argument. Here's an example adapted from tests/regressiontests/forms/tests.py:

>>> def get_choices():
...     for i in range(5):
...         yield (i, i)
>>> w = Select(choices=get_choices())
>>> print w.render('num',2)
<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
>>> print w.render('num',2)
<select name="num">
</select>

Platform: Python v. 2.4.3 on cygwin

I think this problem occurs because a generator object created by a generator function or a generator expression can only be iterated over once.

A work-around is to create a sequence type from the generator:

>>> def get_choices():
...     for i in range(5):
...         yield (i, i)
>>> w = Select(choices=tuple(get_choices()))
>>> print w.render('num',2)
<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
>>> print w.render('num',2)
<select name="num">
<option value="0">0</option>
<option value="1">1</option>
<option value="2" selected="selected">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>

The documentation should either state that the choices argument to Select.init() should not be a generator, or the widget should convert the generator object to a sequence and save a copy so that the behavior of Select.render() is consistent regardless of how many times it is called.

Change History (2)

comment:1 Changed 8 years ago by adrian

  • Triage Stage changed from Unreviewed to Accepted

Good catch!

comment:2 Changed 8 years ago by adrian

  • Resolution set to fixed
  • Status changed from new to closed

(In [4435]) Fixed #3300 -- Changed newforms Select widget to collapse 'choices' into a list if it's an iterable, so the iterable can be iterated over multiple times.

Note: See TracTickets for help on using tickets.
Back to Top