From 8a9c8bb90736451e6bdea82723cbb23a695146fb Mon Sep 17 00:00:00 2001
From: Claude Paroz <claude@2xlibre.net>
Date: Fri, 6 Dec 2013 14:40:51 +0100
Subject: [PATCH] Fixed #21568 -- Added missing ModelMultipleChoiceField
 to_python method

Thanks dibrovsd at gmail.com for the report and Simon Charette
for the review.
---
 django/forms/models.py             |  6 ++++++
 docs/releases/1.6.1.txt            |  3 +++
 tests/model_forms_regress/tests.py | 23 +++++++++++++++++++++++
 3 files changed, 32 insertions(+)

diff --git a/django/forms/models.py b/django/forms/models.py
index 5c2c77cbf2..2d068eba1e 100644
--- a/django/forms/models.py
+++ b/django/forms/models.py
@@ -1175,6 +1175,12 @@ class ModelMultipleChoiceField(ModelChoiceField):
             msg = _('Hold down "Control", or "Command" on a Mac, to select more than one.')
             self.help_text = string_concat(self.help_text, ' ', msg)
 
+    def to_python(self, value):
+        if not value:
+            return []
+        to_py = super(ModelMultipleChoiceField, self).to_python
+        return [to_py(val) for val in value]
+
     def clean(self, value):
         if self.required and not value:
             raise ValidationError(self.error_messages['required'], code='required')
diff --git a/docs/releases/1.6.1.txt b/docs/releases/1.6.1.txt
index 5eeb446b88..2ac8822c9c 100644
--- a/docs/releases/1.6.1.txt
+++ b/docs/releases/1.6.1.txt
@@ -22,6 +22,9 @@ Bug fixes
   raised an error (#21439).
 * Fixed a regression that prevented editable ``GenericRelation`` subclasses
   from working in ``ModelForms``.
+* Added missing ``to_python`` method for ``ModelMultipleChoiceField`` which
+  is required in Django 1.6 to properly detect changes from initial values
+  (#21568).
 * Fixed ``django.contrib.humanize`` translations where the unicode sequence
   for the non-breaking space was returned verbatim (#21415).
 * Fixed :djadmin:`loaddata` error when fixture file name contained any dots
diff --git a/tests/model_forms_regress/tests.py b/tests/model_forms_regress/tests.py
index 963c7e552d..d6c05f3153 100644
--- a/tests/model_forms_regress/tests.py
+++ b/tests/model_forms_regress/tests.py
@@ -45,6 +45,29 @@ class ModelMultipleChoiceFieldTests(TestCase):
         f.clean([p.pk for p in Person.objects.all()[8:9]])
         self.assertTrue(self._validator_run)
 
+    def test_model_multiple_choice_show_hidden_initial(self):
+        """
+        Test support of show_hidden_initial by ModelMultipleChoiceField.
+        """
+        class PersonForm(forms.Form):
+            persons = forms.ModelMultipleChoiceField(show_hidden_initial=True,
+                                                     queryset=Person.objects.all())
+
+        person1 = Person.objects.create(name="Person 1")
+        person2 = Person.objects.create(name="Person 2")
+
+        form = PersonForm(initial={'persons': [person1, person2]},
+                          data={'initial-persons': [str(person1.pk), str(person2.pk)],
+                                'persons': [str(person1.pk), str(person2.pk)]})
+        self.assertTrue(form.is_valid())
+        self.assertFalse(form.has_changed())
+
+        form = PersonForm(initial={'persons': [person1, person2]},
+                          data={'initial-persons': [str(person1.pk), str(person2.pk)],
+                                'persons': [str(person2.pk)]})
+        self.assertTrue(form.is_valid())
+        self.assertTrue(form.has_changed())
+
 
 class TripleForm(forms.ModelForm):
     class Meta: