diff --git a/django/newforms/forms.py b/django/newforms/forms.py index 22ca2d0bab..09419f9a0d 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -2,7 +2,7 @@ Form classes """ -from django.utils.datastructures import SortedDict +from django.utils.datastructures import SortedDict, MultiValueDict from django.utils.html import escape from fields import Field from widgets import TextInput, Textarea, HiddenInput @@ -221,6 +221,8 @@ class BoundField(StrAndUnicode): def _data(self): "Returns the data for this BoundField, or None if it wasn't given." + if self.field.widget.requires_data_list and isinstance(self.form.data, MultiValueDict): + return self.form.data.getlist(self.name) return self.form.data.get(self.name, None) data = property(_data) diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index 1a2d7d67c9..ba11f35008 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -9,6 +9,7 @@ __all__ = ( ) from util import StrAndUnicode, smart_unicode +from django.utils.datastructures import MultiValueDict from django.utils.html import escape from itertools import chain @@ -64,6 +65,7 @@ class Input(Widget): type='radio', which are special). """ input_type = None # Subclasses must define this. + def render(self, name, value, attrs=None): if value is None: value = '' final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) @@ -146,6 +148,11 @@ class SelectMultiple(Widget): output.append(u'') return u'\n'.join(output) + def value_from_datadict(self, data, name): + if isinstance(data, MultiValueDict): + return data.getlist(name) + return data.get(name, None) + class RadioInput(StrAndUnicode): "An object used by RadioFieldRenderer that represents a single ." def __init__(self, name, value, attrs, choice, index): diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 825b44862d..7752060287 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -1672,6 +1672,23 @@ MultipleChoiceField can also be used with the CheckboxSelectMultiple widget.
+Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict +conveniently work with this. +>>> data = {'name': 'Yesterday', 'composers': ['J', 'P']} +>>> f = SongForm(data) +>>> f.errors +{} +>>> from django.http import QueryDict +>>> data = QueryDict('name=Yesterday&composers=J&composers=P') +>>> f = SongForm(data) +>>> f.errors +{} +>>> from django.utils.datastructures import MultiValueDict +>>> data = MultiValueDict(dict(name='Yesterday', composers=['J', 'P'])) +>>> f = SongForm(data) +>>> f.errors +{} + When using CheckboxSelectMultiple, the framework expects a list of input and returns a list of input. >>> f = SongForm({'name': 'Yesterday'}, auto_id=False)