From cdc25ac4747bf5a6cdc2e70461c2d43c54529d35 Mon Sep 17 00:00:00 2001 From: Niclas Olofsson Date: Sat, 26 Jul 2014 11:06:30 +0200 Subject: [PATCH] Fixed #22808 -- Made ModelMultipleChoiceField validation more robust to invalid data types.. Thanks Mattias Lindvall for the report and inital patch. --- AUTHORS | 1 + django/forms/models.py | 4 ++-- tests/model_forms/tests.py | 13 +++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/AUTHORS b/AUTHORS index 5a92b0c539..a1956881cc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -458,6 +458,7 @@ answer newbie questions, and generally made Django that much better: Todd O'Bryan Alex Ogier Joao Oliveira + Niclas Olofsson Selwin Ong Gerardo Orozco Christian Oudard diff --git a/django/forms/models.py b/django/forms/models.py index 5838ac1631..fb342b3316 100644 --- a/django/forms/models.py +++ b/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', diff --git a/tests/model_forms/tests.py b/tests/model_forms/tests.py index 03a498c4cd..3efc724c38 100644 --- a/tests/model_forms/tests.py +++ b/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.