Browse Source

Fixed #23098 -- Checked that lazy choices are not evaluated too soon

Thanks Matthieu Agopian for the report.
Florian Apolloner 10 years ago
parent
commit
2f73b527dd
2 changed files with 13 additions and 4 deletions
  1. 6 4
      django/db/models/fields/__init__.py
  2. 7 0
      tests/model_fields/tests.py

+ 6 - 4
django/db/models/fields/__init__.py

@@ -730,10 +730,12 @@ class Field(RegisterLookupMixin):
         """Returns choices with a default blank choices included, for use
         as SelectField choices for this field."""
         blank_defined = False
-        for choice, __ in self.choices:
-            if choice in ('', None):
-                blank_defined = True
-                break
+        named_groups = self.choices and isinstance(self.choices[0][1], (list, tuple))
+        if not named_groups:
+            for choice, __ in self.choices:
+                if choice in ('', None):
+                    blank_defined = True
+                    break
 
         first_choice = (blank_choice if include_blank and
                         not blank_defined else [])

+ 7 - 0
tests/model_fields/tests.py

@@ -416,6 +416,13 @@ class ValidationTest(test.TestCase):
         f = models.CharField(choices=[('', '<><>'), ('a', 'A')])
         self.assertEqual(f.get_choices(True), [('', '<><>'), ('a', 'A')])
 
+    def test_charfield_get_choices_doesnt_evaluate_lazy_strings(self):
+        # Regression test for #23098
+        # Will raise ZeroDivisionError if lazy is evaluated
+        lazy_func = lazy(lambda x: 0/0, int)
+        f = models.CharField(choices=[(lazy_func('group'), (('a', 'A'), ('b', 'B')))])
+        self.assertEqual(f.get_choices(True)[0], ('', '---------'))
+
     def test_choices_validation_supports_named_groups(self):
         f = models.IntegerField(
             choices=(('group', ((10, 'A'), (20, 'B'))), (30, 'C')))