Fixed #3193 -- newforms: Modified as_hidden() to handle MultipleChoiceField correctly. Thanks for the report, Honza Kral

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4298 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2007-01-09 05:12:25 +00:00
parent 2e148d7064
commit fb60a6ff0a
4 changed files with 31 additions and 5 deletions

View File

@ -4,7 +4,7 @@ Field classes
from django.utils.translation import gettext from django.utils.translation import gettext
from util import ValidationError, smart_unicode from util import ValidationError, smart_unicode
from widgets import TextInput, PasswordInput, CheckboxInput, Select, SelectMultiple from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, CheckboxInput, Select, SelectMultiple
import datetime import datetime
import re import re
import time import time
@ -29,6 +29,7 @@ except NameError:
class Field(object): class Field(object):
widget = TextInput # Default widget to use when rendering this type of Field. widget = TextInput # Default widget to use when rendering this type of Field.
hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
# Tracks each time a Field instance is created. Used to retain order. # Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0 creation_counter = 0
@ -336,6 +337,8 @@ class ChoiceField(Field):
return value return value
class MultipleChoiceField(ChoiceField): class MultipleChoiceField(ChoiceField):
hidden_widget = MultipleHiddenInput
def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None): def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None):
ChoiceField.__init__(self, choices, required, widget, label, initial) ChoiceField.__init__(self, choices, required, widget, label, initial)

View File

@ -5,7 +5,7 @@ Form classes
from django.utils.datastructures import SortedDict, MultiValueDict from django.utils.datastructures import SortedDict, MultiValueDict
from django.utils.html import escape from django.utils.html import escape
from fields import Field from fields import Field
from widgets import TextInput, Textarea, HiddenInput from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput
from util import StrAndUnicode, ErrorDict, ErrorList, ValidationError from util import StrAndUnicode, ErrorDict, ErrorList, ValidationError
__all__ = ('BaseForm', 'Form') __all__ = ('BaseForm', 'Form')
@ -238,7 +238,7 @@ class BoundField(StrAndUnicode):
""" """
Returns a string of HTML for representing this as an <input type="hidden">. Returns a string of HTML for representing this as an <input type="hidden">.
""" """
return self.as_widget(HiddenInput(), attrs) return self.as_widget(self.field.hidden_widget(), attrs)
def _data(self): def _data(self):
""" """

View File

@ -3,8 +3,8 @@ HTML Widget classes
""" """
__all__ = ( __all__ = (
'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput', 'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput',
'Textarea', 'CheckboxInput', 'FileInput', 'Textarea', 'CheckboxInput',
'Select', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple', 'Select', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple',
) )
@ -87,6 +87,16 @@ class HiddenInput(Input):
input_type = 'hidden' input_type = 'hidden'
is_hidden = True is_hidden = True
class MultipleHiddenInput(HiddenInput):
"""
A widget that handles <input type="hidden"> for fields that have a list
of values.
"""
def render(self, name, value, attrs=None):
if value is None: value = []
final_attrs = self.build_attrs(attrs, type=self.input_type, name=name)
return u'\n'.join([(u'<input%s />' % flatatt(dict(value=smart_unicode(v), **final_attrs))) for v in value])
class FileInput(Input): class FileInput(Input):
input_type = 'file' input_type = 'file'

View File

@ -1849,6 +1849,17 @@ MultipleChoiceField is a special case, as its data is required to be a list:
<option value="P" selected="selected">Paul McCartney</option> <option value="P" selected="selected">Paul McCartney</option>
</select> </select>
MultipleChoiceField rendered as_hidden() is a special case. Because it can
have multiple values, its as_hidden() renders multiple <input type="hidden">
tags.
>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False)
>>> print f['composers'].as_hidden()
<input type="hidden" name="composers" value="P" />
>>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False)
>>> print f['composers'].as_hidden()
<input type="hidden" name="composers" value="P" />
<input type="hidden" name="composers" value="J" />
MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. MultipleChoiceField can also be used with the CheckboxSelectMultiple widget.
>>> class SongForm(Form): >>> class SongForm(Form):
... name = CharField() ... name = CharField()
@ -1905,6 +1916,8 @@ returns a list of input.
>>> f.clean_data >>> f.clean_data
{'composers': [u'J', u'P'], 'name': u'Yesterday'} {'composers': [u'J', u'P'], 'name': u'Yesterday'}
# Validating multiple fields in relation to another ###########################
There are a couple of ways to do multiple-field validation. If you want the There are a couple of ways to do multiple-field validation. If you want the
validation message to be associated with a particular field, implement the validation message to be associated with a particular field, implement the
clean_XXX() method on the Form, where XXX is the field name. As in clean_XXX() method on the Form, where XXX is the field name. As in