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

Thanks Mattias Lindvall for the report and inital patch.
This commit is contained in:
Niclas Olofsson 2014-07-26 11:06:30 +02:00 committed by Tim Graham
parent 7579080899
commit cdc25ac474
3 changed files with 16 additions and 2 deletions

View File

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

View File

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

View File

@ -1391,6 +1391,13 @@ class ModelChoiceFieldTests(TestCase):
f.clean(None) f.clean(None)
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
f.clean(0) 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.c2.id).name, "It's a test")
self.assertEqual(f.clean(self.c3.id).name, 'Third') self.assertEqual(f.clean(self.c3.id).name, 'Third')
@ -1495,6 +1502,12 @@ class ModelMultipleChoiceFieldTests(TestCase):
with self.assertRaises(ValidationError): with self.assertRaises(ValidationError):
f.clean(['fail']) 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 # Add a Category object *after* the ModelMultipleChoiceField has already been
# instantiated. This proves clean() checks the database during clean() rather # instantiated. This proves clean() checks the database during clean() rather
# than caching it at time of instantiation. # than caching it at time of instantiation.