Opened 9 years ago

Closed 9 years ago

Last modified 9 years ago

#2265 closed defect (fixed)

[patch] Field's choices can be "used" only once if its a generator or an iterator.

Reported by: Alex Dedul Owned by: adrian
Component: Core (Other) Version:
Severity: normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

If you have field with an iterator/generator for choices its correct display value could be fetched only once. For example:

>>> from intranet.orders.models import SSL
>>> s = SSL.objects.get(pk=1)
>>> s.get_country_display()
'Belarus'
>>> s.get_country_display()
'BY'
>>> s.get_country_display()
'BY'

Its apparent that its because of the nature of iterators that can be "listed" only once. Proposed patch to fix this uses itertools.tee for every field.choices that looks like an iterator. Hardly its perfect, cos tee is caching values. Maybe someone could come up with a better solution.

Also there should be tests for this, but lets see what core devs says for now.

Attachments (2)

iterator_choices.patch (1.4 KB) - added by Alex Dedul 9 years ago.
iterator_choices_try2.patch (2.2 KB) - added by Alex Dedul 9 years ago.

Download all attachments as: .zip

Change History (7)

Changed 9 years ago by Alex Dedul

comment:1 Changed 9 years ago by mtredinnick

All Django code must be Python 2.3 compatible and itertools.tee was only introduced in Python 2.4.

Also, why not just do self.choices = list(choices) if you want to cache the values? The iterator interface supports coercing to a list. Am I missing something tricky (besides completely defeating the purpose of using an iterator in the first place; but not being able to use it more than once seems like an even bigger bug).

comment:2 Changed 9 years ago by Alex Dedul

As for me i'm using generator to fetch choices list from DB on external host and advanges of lazy fetching should be seen quite well here.

As for itertools.tee replacement self.choices = list(choices) is no go, list() fetches values from iterator right away. What we need from fix is:

  1. Cache values.
  2. Lazy fetching.

itertools.tee does exactly that.

comment:3 Changed 9 years ago by adrian

Alex -- Given that itertools.tee is not available in Python 2.3, do you have an idea for another solution?

comment:4 Changed 9 years ago by Alex Dedul

As it turns out there is already implementation of tee() for python 2.3 http://www.python.org/doc/2.3.5/lib/itertools-example.html . Attached another version of patch based on that code.

Changed 9 years ago by Alex Dedul

comment:5 Changed 9 years ago by mtredinnick

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

(In [3851]) Fixed #2265 -- Fixed problem with using iterators for "choices" attribute.
Thanks, Alex Dedul.

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