Browse Source

Fixed #22808 -- Made ModelMultipleChoiceField validation more robust to invalid data types..

Thanks Mattias Lindvall for the report and inital patch.
Niclas Olofsson 10 years ago
parent
commit
cdc25ac474
3 changed files with 16 additions and 2 deletions
  1. 1 0
      AUTHORS
  2. 2 2
      django/forms/models.py
  3. 13 0
      tests/model_forms/tests.py

+ 1 - 0
AUTHORS

@@ -458,6 +458,7 @@ answer newbie questions, and generally made Django that much better:
     Todd O'Bryan <toddobryan@mac.com>
     Alex Ogier <alex.ogier@gmail.com>
     Joao Oliveira <joaoxsouls@gmail.com>
+    Niclas Olofsson <n@niclasolofsson.se>
     Selwin Ong <selwin@ui.co.id>
     Gerardo Orozco <gerardo.orozco.mosqueda@gmail.com>
     Christian Oudard <christian.oudard@gmail.com>

+ 2 - 2
django/forms/models.py

@@ -1179,7 +1179,7 @@ class ModelChoiceField(ChoiceField):
         try:
             key = self.to_field_name or 'pk'
             value = self.queryset.get(**{key: value})
-        except (ValueError, self.queryset.model.DoesNotExist):
+        except (ValueError, TypeError, self.queryset.model.DoesNotExist):
             raise ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')
         return value
 
@@ -1227,7 +1227,7 @@ class ModelMultipleChoiceField(ModelChoiceField):
         for pk in value:
             try:
                 self.queryset.filter(**{key: pk})
-            except ValueError:
+            except (ValueError, TypeError):
                 raise ValidationError(
                     self.error_messages['invalid_pk_value'],
                     code='invalid_pk_value',

+ 13 - 0
tests/model_forms/tests.py

@@ -1391,6 +1391,13 @@ class ModelChoiceFieldTests(TestCase):
             f.clean(None)
         with self.assertRaises(ValidationError):
             f.clean(0)
+
+        # Invalid types that require TypeError to be caught (#22808).
+        with self.assertRaises(ValidationError):
+            f.clean([['fail']])
+        with self.assertRaises(ValidationError):
+            f.clean([{'foo': 'bar'}])
+
         self.assertEqual(f.clean(self.c2.id).name, "It's a test")
         self.assertEqual(f.clean(self.c3.id).name, 'Third')
 
@@ -1495,6 +1502,12 @@ class ModelMultipleChoiceFieldTests(TestCase):
         with self.assertRaises(ValidationError):
             f.clean(['fail'])
 
+        # Invalid types that require TypeError to be caught (#22808).
+        with self.assertRaises(ValidationError):
+            f.clean([['fail']])
+        with self.assertRaises(ValidationError):
+            f.clean([{'foo': 'bar'}])
+
         # Add a Category object *after* the ModelMultipleChoiceField has already been
         # instantiated. This proves clean() checks the database during clean() rather
         # than caching it at time of instantiation.