[1.5.x] Fixed #18172 -- Made models with __iter__ usable in ModelMultipleChoiceField

Thanks to Patryk Zawadzki for the patch.

Backpatch of 3989ce52ef
This commit is contained in:
Patryk Zawadzki 2012-12-19 19:12:08 +01:00 committed by Anssi Kääriäinen
parent 470f3eca34
commit 9892919b0d
3 changed files with 33 additions and 2 deletions

View File

@ -1033,6 +1033,8 @@ class ModelMultipleChoiceField(ModelChoiceField):
return qs return qs
def prepare_value(self, value): 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(v) for v in value]
return super(ModelMultipleChoiceField, self).prepare_value(value) return super(ModelMultipleChoiceField, self).prepare_value(value)

View File

@ -263,3 +263,18 @@ class FlexibleDatePost(models.Model):
slug = models.CharField(max_length=50, unique_for_year='posted', blank=True) slug = models.CharField(max_length=50, unique_for_year='posted', blank=True)
subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True) subtitle = models.CharField(max_length=50, unique_for_month='posted', blank=True)
posted = models.DateField(blank=True, null=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)

View File

@ -19,7 +19,8 @@ from .models import (Article, ArticleStatus, BetterWriter, BigInt, Book,
Category, CommaSeparatedInteger, CustomFieldForExclusionModel, DerivedBook, Category, CommaSeparatedInteger, CustomFieldForExclusionModel, DerivedBook,
DerivedPost, ExplicitPK, FlexibleDatePost, ImprovedArticle, DerivedPost, ExplicitPK, FlexibleDatePost, ImprovedArticle,
ImprovedArticleWithParentLink, Inventory, Post, Price, ImprovedArticleWithParentLink, Inventory, Post, Price,
Product, TextFile, Writer, WriterProfile, test_images) Product, TextFile, Writer, WriterProfile, Colour, ColourfulItem,
test_images)
if test_images: if test_images:
from .models import ImageFile, OptionalImageFile from .models import ImageFile, OptionalImageFile
@ -174,6 +175,10 @@ class PriceFormWithoutQuantity(forms.ModelForm):
model = Price model = Price
exclude = ('quantity',) exclude = ('quantity',)
class ColourfulItemForm(forms.ModelForm):
class Meta:
model = ColourfulItem
class ModelFormBaseTest(TestCase): class ModelFormBaseTest(TestCase):
def test_base_form(self): def test_base_form(self):
@ -1515,3 +1520,12 @@ class OldFormForXTests(TestCase):
['name']) ['name'])
self.assertHTMLEqual(six.text_type(CustomFieldForExclusionForm()), 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>''') '''<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>""")