Opened 13 years ago

Closed 13 years ago

Last modified 12 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 Holovaty
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: no UI/UX: no


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()
>>> s.get_country_display()
>>> s.get_country_display()

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 13 years ago.
iterator_choices_try2.patch (2.2 KB) - added by Alex Dedul 13 years ago.

Download all attachments as: .zip

Change History (7)

Changed 13 years ago by Alex Dedul

Attachment: iterator_choices.patch added

comment:1 Changed 13 years ago by Malcolm Tredinnick

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 13 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 13 years ago by Adrian Holovaty

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

comment:4 Changed 13 years ago by Alex Dedul

As it turns out there is already implementation of tee() for python 2.3 . Attached another version of patch based on that code.

Changed 13 years ago by Alex Dedul

Attachment: iterator_choices_try2.patch added

comment:5 Changed 13 years ago by Malcolm Tredinnick

Resolution: fixed
Status: newclosed

(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