@@ -1174,8 +1174,7 @@ def __init__(self, queryset, cache_choices=False, required=True,
11741174 def to_python (self , value ):
11751175 if not value :
11761176 return []
1177- to_py = super (ModelMultipleChoiceField , self ).to_python
1178- return [to_py (val ) for val in value ]
1177+ return list (self ._check_values (value ))
11791178
11801179 def clean (self , value ):
11811180 if self .required and not value :
@@ -1184,7 +1183,29 @@ def clean(self, value):
11841183 return self .queryset .none ()
11851184 if not isinstance (value , (list , tuple )):
11861185 raise ValidationError (self .error_messages ['list' ], code = 'list' )
1186+ qs = self ._check_values (value )
1187+ # Since this overrides the inherited ModelChoiceField.clean
1188+ # we run custom validators here
1189+ self .run_validators (value )
1190+ return qs
1191+
1192+ def _check_values (self , value ):
1193+ """
1194+ Given a list of possible PK values, returns a QuerySet of the
1195+ corresponding objects. Raises a ValidationError if a given value is
1196+ invalid (not a valid PK, not in the queryset, etc.)
1197+ """
11871198 key = self .to_field_name or 'pk'
1199+ # deduplicate given values to avoid creating many querysets or
1200+ # requiring the database backend deduplicate efficiently.
1201+ try :
1202+ value = frozenset (value )
1203+ except TypeError :
1204+ # list of lists isn't hashable, for example
1205+ raise ValidationError (
1206+ self .error_messages ['list' ],
1207+ code = 'list' ,
1208+ )
11881209 for pk in value :
11891210 try :
11901211 self .queryset .filter (** {key : pk })
@@ -1203,9 +1224,6 @@ def clean(self, value):
12031224 code = 'invalid_choice' ,
12041225 params = {'value' : val },
12051226 )
1206- # Since this overrides the inherited ModelChoiceField.clean
1207- # we run custom validators here
1208- self .run_validators (value )
12091227 return qs
12101228
12111229 def prepare_value (self , value ):
0 commit comments