Fixed #2265 -- Fixed problem with using iterators for "choices" attribute.

Thanks, Alex Dedul.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@3851 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Malcolm Tredinnick 2006-09-26 06:33:32 +00:00
parent be053df693
commit a27f12f388
2 changed files with 41 additions and 1 deletions

View File

@ -5,6 +5,7 @@ from django.core import validators
from django import forms from django import forms
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.functional import curry from django.utils.functional import curry
from django.utils.itercompat import tee
from django.utils.text import capfirst from django.utils.text import capfirst
from django.utils.translation import gettext, gettext_lazy from django.utils.translation import gettext, gettext_lazy
import datetime, os, time import datetime, os, time
@ -80,7 +81,7 @@ class Field(object):
self.prepopulate_from = prepopulate_from self.prepopulate_from = prepopulate_from
self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month
self.unique_for_year = unique_for_year self.unique_for_year = unique_for_year
self.choices = choices or [] self._choices = choices or []
self.radio_admin = radio_admin self.radio_admin = radio_admin
self.help_text = help_text self.help_text = help_text
self.db_column = db_column self.db_column = db_column
@ -324,6 +325,14 @@ class Field(object):
def bind(self, fieldmapping, original, bound_field_class): def bind(self, fieldmapping, original, bound_field_class):
return bound_field_class(self, fieldmapping, original) return bound_field_class(self, fieldmapping, original)
def _get_choices(self):
if hasattr(self._choices, 'next'):
choices, self._choices = tee(self._choices)
return choices
else:
return self._choices
choices = property(_get_choices)
class AutoField(Field): class AutoField(Field):
empty_strings_allowed = False empty_strings_allowed = False
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View File

@ -0,0 +1,31 @@
"""
Providing iterator functions that are not in all version of Python we support.
Where possible, we try to use the system-native version and only fall back to
these implementations if necessary.
"""
import itertools
def compat_tee(iterable):
"""Return two independent iterators from a single iterable.
Based on http://www.python.org/doc/2.3.5/lib/itertools-example.html
"""
# Note: Using a dictionary and a list as the default arguments here is
# deliberate and safe in this instance.
def gen(next, data={}, cnt=[0]):
dpop = data.pop
for i in count():
if i == cnt[0]:
item = data[i] = next()
cnt[0] += 1
else:
item = dpop(i)
yield item
next = iter(iterable).next
return gen(next), gen(next)
if hasattr(itertools, 'tee'):
tee = itertools.tee
else:
tee = compat_tee