summaryrefslogtreecommitdiff
path: root/django/forms
diff options
context:
space:
mode:
Diffstat (limited to 'django/forms')
-rw-r--r--django/forms/models.py28
1 files changed, 23 insertions, 5 deletions
diff --git a/django/forms/models.py b/django/forms/models.py
index 34ff3c478c..1ec1398147 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -1232,8 +1232,7 @@ class ModelMultipleChoiceField(ModelChoiceField):
def to_python(self, value):
if not value:
return []
- to_py = super(ModelMultipleChoiceField, self).to_python
- return [to_py(val) for val in value]
+ return list(self._check_values(value))
def clean(self, value):
if self.required and not value:
@@ -1242,7 +1241,29 @@ class ModelMultipleChoiceField(ModelChoiceField):
return self.queryset.none()
if not isinstance(value, (list, tuple)):
raise ValidationError(self.error_messages['list'], code='list')
+ qs = self._check_values(value)
+ # Since this overrides the inherited ModelChoiceField.clean
+ # we run custom validators here
+ self.run_validators(value)
+ return qs
+
+ def _check_values(self, value):
+ """
+ Given a list of possible PK values, returns a QuerySet of the
+ corresponding objects. Raises a ValidationError if a given value is
+ invalid (not a valid PK, not in the queryset, etc.)
+ """
key = self.to_field_name or 'pk'
+ # deduplicate given values to avoid creating many querysets or
+ # requiring the database backend deduplicate efficiently.
+ try:
+ value = frozenset(value)
+ except TypeError:
+ # list of lists isn't hashable, for example
+ raise ValidationError(
+ self.error_messages['list'],
+ code='list',
+ )
for pk in value:
try:
self.queryset.filter(**{key: pk})
@@ -1261,9 +1282,6 @@ class ModelMultipleChoiceField(ModelChoiceField):
code='invalid_choice',
params={'value': val},
)
- # Since this overrides the inherited ModelChoiceField.clean
- # we run custom validators here
- self.run_validators(value)
return qs
def prepare_value(self, value):