From 661f62be3c5f810fddd3b33bcbdfe33a3077a66d Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Sun, 27 Jul 2008 07:22:39 +0000 Subject: [PATCH] Fixed #7913 -- Corrected backwards incompatible parts of [7977] when optgroup handling was added to field choices (Ticket #4412). Thanks to Michael Elsdorfer (miracle2k) for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8102 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/fields/__init__.py | 15 ++++-- tests/modeltests/choices/models.py | 11 +++++ tests/regressiontests/model_fields/models.py | 51 ++++++++++++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 439633c45f..dd5117fb78 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -288,7 +288,7 @@ class Field(object): if self.choices: field_objs = [oldforms.SelectField] - params['choices'] = self.flatchoices + params['choices'] = self.get_flatchoices() else: field_objs = self.get_manipulator_field_objs() return (field_objs, params) @@ -362,7 +362,8 @@ class Field(object): return val def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): - "Returns a list of tuples used as SelectField choices for this field." + """Returns choices with a default blank choices included, for use + as SelectField choices for this field.""" first_choice = include_blank and blank_choice or [] if self.choices: return first_choice + list(self.choices) @@ -376,6 +377,11 @@ class Field(object): def get_choices_default(self): return self.get_choices() + def get_flatchoices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): + "Returns flattened choices with a default blank choice included." + first_choice = include_blank and blank_choice or [] + return first_choices + list(self.flatchoices) + def _get_val_from_obj(self, obj): if obj: return getattr(obj, self.attname) @@ -408,15 +414,16 @@ class Field(object): choices = property(_get_choices) def _get_flatchoices(self): + """Flattened version of choices tuple.""" flat = [] - for choice, value in self.get_choices_default(): + for choice, value in self.choices: if type(value) in (list, tuple): flat.extend(value) else: flat.append((choice,value)) return flat flatchoices = property(_get_flatchoices) - + def save_form_data(self, instance, data): setattr(instance, self.name, data) diff --git a/tests/modeltests/choices/models.py b/tests/modeltests/choices/models.py index 550e655e46..e378260598 100644 --- a/tests/modeltests/choices/models.py +++ b/tests/modeltests/choices/models.py @@ -36,4 +36,15 @@ __test__ = {'API_TESTS':""" u'Male' >>> s.get_gender_display() u'Female' + +# If the value for the field doesn't correspond to a valid choice, +# the value itself is provided as a display value. +>>> a.gender = '' +>>> a.get_gender_display() +u'' + +>>> a.gender = 'U' +>>> a.get_gender_display() +u'U' + """} diff --git a/tests/regressiontests/model_fields/models.py b/tests/regressiontests/model_fields/models.py index 7e07227961..9936184606 100644 --- a/tests/regressiontests/model_fields/models.py +++ b/tests/regressiontests/model_fields/models.py @@ -11,6 +11,22 @@ class Bar(models.Model): b = models.CharField(max_length=10) a = models.ForeignKey(Foo, default=get_foo) +class Whiz(models.Model): + CHOICES = ( + ('Group 1', ( + (1,'First'), + (2,'Second'), + ) + ), + ('Group 2', ( + (3,'Third'), + (4,'Fourth'), + ) + ), + (0,'Other'), + ) + c = models.IntegerField(choices=CHOICES, null=True) + __test__ = {'API_TESTS':""" # Create a couple of Places. >>> f = Foo.objects.create(a='abc') @@ -21,4 +37,39 @@ __test__ = {'API_TESTS':""" >>> b.save() +# Regression tests for #7913 +# Check that get_choices and get_flatchoices interact with +# get_FIELD_display to return the expected values. + +# Test a nested value +>>> w = Whiz(c=1) +>>> w.save() +>>> w.get_c_display() +u'First' + +# Test a top level value +>>> w.c = 0 +>>> w.save() +>>> w.get_c_display() +u'Other' + +# Test an invalid data value +>>> w.c = 9 +>>> w.save() +>>> w.get_c_display() +9 + +# Test a blank data value +>>> w.c = None +>>> w.save() +>>> print w.get_c_display() +None + +# Test an empty data value +>>> w.c = '' +>>> w.save() +>>> w.get_c_display() +u'' + + """}