Loading django/forms/models.py +1 −1 Original line number Diff line number Diff line Loading @@ -1013,7 +1013,7 @@ class ModelMultipleChoiceField(ModelChoiceField): if self.required and not value: raise ValidationError(self.error_messages['required']) elif not self.required and not value: return [] return self.queryset.none() if not isinstance(value, (list, tuple)): raise ValidationError(self.error_messages['list']) key = self.to_field_name or 'pk' Loading docs/ref/forms/fields.txt +6 −2 Original line number Diff line number Diff line Loading @@ -997,13 +997,17 @@ objects (in the case of ``ModelMultipleChoiceField``) into the .. class:: ModelMultipleChoiceField(**kwargs) * Default widget: ``SelectMultiple`` * Empty value: ``[]`` (an empty list) * Normalizes to: A list of model instances. * Empty value: An empty ``QuerySet`` (self.queryset.none()) * Normalizes to: A ``QuerySet`` of model instances. * Validates that every id in the given list of values exists in the queryset. * Error message keys: ``required``, ``list``, ``invalid_choice``, ``invalid_pk_value`` .. versionchanged:: 1.5 The empty and normalized values were changed to be consistently ``QuerySets`` instead of ``[]`` and ``QuerySet`` respectively. Allows the selection of one or more model objects, suitable for representing a many-to-many relation. As with :class:`ModelChoiceField`, you can use ``label_from_instance`` to customize the object Loading docs/releases/1.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -422,6 +422,9 @@ on the form. Miscellaneous ~~~~~~~~~~~~~ * :class:`django.forms.ModelMultipleChoiceField` now returns an empty ``QuerySet`` as the empty value instead of an empty list. * :func:`~django.utils.http.int_to_base36` properly raises a :exc:`TypeError` instead of :exc:`ValueError` for non-integer inputs. Loading tests/modeltests/model_forms/tests.py +3 −2 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ from django import forms from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import ValidationError from django.db import connection from django.db.models.query import EmptyQuerySet from django.forms.models import model_to_dict from django.utils.unittest import skipUnless from django.test import TestCase Loading Loading @@ -1035,8 +1036,8 @@ class OldFormForXTests(TestCase): f.clean([c6.id]) f = forms.ModelMultipleChoiceField(Category.objects.all(), required=False) self.assertEqual(f.clean([]), []) self.assertEqual(f.clean(()), []) self.assertIsInstance(f.clean([]), EmptyQuerySet) self.assertIsInstance(f.clean(()), EmptyQuerySet) with self.assertRaises(ValidationError): f.clean(['10']) with self.assertRaises(ValidationError): Loading tests/regressiontests/forms/models.py +6 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,12 @@ class ChoiceFieldModel(models.Model): multi_choice_int = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice_int', default=lambda: [1]) class OptionalMultiChoiceModel(models.Model): multi_choice = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='not_relevant', default=lambda: ChoiceOptionModel.objects.filter(name='default')) multi_choice_optional = models.ManyToManyField(ChoiceOptionModel, blank=True, null=True, related_name='not_relevant2') class FileModel(models.Model): file = models.FileField(storage=temp_storage, upload_to='tests') Loading Loading
django/forms/models.py +1 −1 Original line number Diff line number Diff line Loading @@ -1013,7 +1013,7 @@ class ModelMultipleChoiceField(ModelChoiceField): if self.required and not value: raise ValidationError(self.error_messages['required']) elif not self.required and not value: return [] return self.queryset.none() if not isinstance(value, (list, tuple)): raise ValidationError(self.error_messages['list']) key = self.to_field_name or 'pk' Loading
docs/ref/forms/fields.txt +6 −2 Original line number Diff line number Diff line Loading @@ -997,13 +997,17 @@ objects (in the case of ``ModelMultipleChoiceField``) into the .. class:: ModelMultipleChoiceField(**kwargs) * Default widget: ``SelectMultiple`` * Empty value: ``[]`` (an empty list) * Normalizes to: A list of model instances. * Empty value: An empty ``QuerySet`` (self.queryset.none()) * Normalizes to: A ``QuerySet`` of model instances. * Validates that every id in the given list of values exists in the queryset. * Error message keys: ``required``, ``list``, ``invalid_choice``, ``invalid_pk_value`` .. versionchanged:: 1.5 The empty and normalized values were changed to be consistently ``QuerySets`` instead of ``[]`` and ``QuerySet`` respectively. Allows the selection of one or more model objects, suitable for representing a many-to-many relation. As with :class:`ModelChoiceField`, you can use ``label_from_instance`` to customize the object Loading
docs/releases/1.5.txt +3 −0 Original line number Diff line number Diff line Loading @@ -422,6 +422,9 @@ on the form. Miscellaneous ~~~~~~~~~~~~~ * :class:`django.forms.ModelMultipleChoiceField` now returns an empty ``QuerySet`` as the empty value instead of an empty list. * :func:`~django.utils.http.int_to_base36` properly raises a :exc:`TypeError` instead of :exc:`ValueError` for non-integer inputs. Loading
tests/modeltests/model_forms/tests.py +3 −2 Original line number Diff line number Diff line Loading @@ -8,6 +8,7 @@ from django import forms from django.core.files.uploadedfile import SimpleUploadedFile from django.core.validators import ValidationError from django.db import connection from django.db.models.query import EmptyQuerySet from django.forms.models import model_to_dict from django.utils.unittest import skipUnless from django.test import TestCase Loading Loading @@ -1035,8 +1036,8 @@ class OldFormForXTests(TestCase): f.clean([c6.id]) f = forms.ModelMultipleChoiceField(Category.objects.all(), required=False) self.assertEqual(f.clean([]), []) self.assertEqual(f.clean(()), []) self.assertIsInstance(f.clean([]), EmptyQuerySet) self.assertIsInstance(f.clean(()), EmptyQuerySet) with self.assertRaises(ValidationError): f.clean(['10']) with self.assertRaises(ValidationError): Loading
tests/regressiontests/forms/models.py +6 −0 Original line number Diff line number Diff line Loading @@ -63,6 +63,12 @@ class ChoiceFieldModel(models.Model): multi_choice_int = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice_int', default=lambda: [1]) class OptionalMultiChoiceModel(models.Model): multi_choice = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='not_relevant', default=lambda: ChoiceOptionModel.objects.filter(name='default')) multi_choice_optional = models.ManyToManyField(ChoiceOptionModel, blank=True, null=True, related_name='not_relevant2') class FileModel(models.Model): file = models.FileField(storage=temp_storage, upload_to='tests') Loading