Skip to content

Commit

Permalink
Fixed django#18172 -- Made models with __iter__ usable in ModelMultip…
Browse files Browse the repository at this point in the history
…leChoiceField

Thanks to Patryk Zawadzki for the patch.
  • Loading branch information
patrys authored and akaariai committed Dec 19, 2012
1 parent abd0f30 commit 3989ce5
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 2 deletions.
4 changes: 3 additions & 1 deletion django/forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1033,6 +1033,8 @@ def clean(self, value):
return qs

def prepare_value(self, value):
if hasattr(value, '__iter__') and not isinstance(value, six.text_type):
if (hasattr(value, '__iter__') and
not isinstance(value, six.text_type) and
not hasattr(value, '_meta')):
return [super(ModelMultipleChoiceField, self).prepare_value(v) for v in value]
return super(ModelMultipleChoiceField, self).prepare_value(value)
15 changes: 15 additions & 0 deletions tests/modeltests/model_forms/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,18 @@ class FlexibleDatePost(models.Model):
slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
posted = models.DateField(blank=True, null=True)

@python_2_unicode_compatible
class Colour(models.Model):
name = models.CharField(max_length=50)

def __iter__(self):
for number in xrange(5):
yield number

def __str__(self):
return self.name

class ColourfulItem(models.Model):
name = models.CharField(max_length=50)
colours = models.ManyToManyField(Colour)
16 changes: 15 additions & 1 deletion tests/modeltests/model_forms/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
Category, CommaSeparatedInteger, CustomFieldForExclusionModel, DerivedBook,
DerivedPost, ExplicitPK, FlexibleDatePost, ImprovedArticle,
ImprovedArticleWithParentLink, Inventory, Post, Price,
Product, TextFile, Writer, WriterProfile, test_images)
Product, TextFile, Writer, WriterProfile, Colour, ColourfulItem,
test_images)

if test_images:
from .models import ImageFile, OptionalImageFile
Expand Down Expand Up @@ -174,6 +175,10 @@ class Meta:
model = Price
exclude = ('quantity',)

class ColourfulItemForm(forms.ModelForm):
class Meta:
model = ColourfulItem


class ModelFormBaseTest(TestCase):
def test_base_form(self):
Expand Down Expand Up @@ -1518,3 +1523,12 @@ def test_model_field_that_returns_none_to_exclude_itself_with_explicit_fields(se
['name'])
self.assertHTMLEqual(six.text_type(CustomFieldForExclusionForm()),
'''<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="10" /></td></tr>''')

def test_iterable_model_m2m(self) :
colour = Colour.objects.create(name='Blue')
form = ColourfulItemForm()
self.maxDiff = 1024
self.assertHTMLEqual(form.as_p(), """<p><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="50" /></p>
<p><label for="id_colours">Colours:</label> <select multiple="multiple" name="colours" id="id_colours">
<option value="1">Blue</option>
</select> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p>""")

0 comments on commit 3989ce5

Please sign in to comment.