From fb60a6ff0acc84417ced061e83bb170fff351b59 Mon Sep 17 00:00:00 2001 From: Adrian Holovaty Date: Tue, 9 Jan 2007 05:12:25 +0000 Subject: [PATCH] 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 --- django/newforms/fields.py | 5 ++++- django/newforms/forms.py | 4 ++-- django/newforms/widgets.py | 14 ++++++++++++-- tests/regressiontests/forms/tests.py | 13 +++++++++++++ 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/django/newforms/fields.py b/django/newforms/fields.py index 408c90df453..e3c1cee87a0 100644 --- a/django/newforms/fields.py +++ b/django/newforms/fields.py @@ -4,7 +4,7 @@ Field classes from django.utils.translation import gettext 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 re import time @@ -29,6 +29,7 @@ except NameError: class Field(object): 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. creation_counter = 0 @@ -336,6 +337,8 @@ class ChoiceField(Field): return value class MultipleChoiceField(ChoiceField): + hidden_widget = MultipleHiddenInput + def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None): ChoiceField.__init__(self, choices, required, widget, label, initial) diff --git a/django/newforms/forms.py b/django/newforms/forms.py index e1cc566b3bc..21c9722990b 100644 --- a/django/newforms/forms.py +++ b/django/newforms/forms.py @@ -5,7 +5,7 @@ Form classes from django.utils.datastructures import SortedDict, MultiValueDict from django.utils.html import escape from fields import Field -from widgets import TextInput, Textarea, HiddenInput +from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput from util import StrAndUnicode, ErrorDict, ErrorList, ValidationError __all__ = ('BaseForm', 'Form') @@ -238,7 +238,7 @@ class BoundField(StrAndUnicode): """ Returns a string of HTML for representing this as an . """ - return self.as_widget(HiddenInput(), attrs) + return self.as_widget(self.field.hidden_widget(), attrs) def _data(self): """ diff --git a/django/newforms/widgets.py b/django/newforms/widgets.py index 996e353775d..df8bb19c4f7 100644 --- a/django/newforms/widgets.py +++ b/django/newforms/widgets.py @@ -3,8 +3,8 @@ HTML Widget classes """ __all__ = ( - 'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'FileInput', - 'Textarea', 'CheckboxInput', + 'Widget', 'TextInput', 'PasswordInput', 'HiddenInput', 'MultipleHiddenInput', + 'FileInput', 'Textarea', 'CheckboxInput', 'Select', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple', ) @@ -87,6 +87,16 @@ class HiddenInput(Input): input_type = 'hidden' is_hidden = True +class MultipleHiddenInput(HiddenInput): + """ + A widget that handles 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'' % flatatt(dict(value=smart_unicode(v), **final_attrs))) for v in value]) + class FileInput(Input): input_type = 'file' diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index d1202944d01..3b252fb5a9c 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -1849,6 +1849,17 @@ MultipleChoiceField is a special case, as its data is required to be a list: +MultipleChoiceField rendered as_hidden() is a special case. Because it can +have multiple values, its as_hidden() renders multiple +tags. +>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) +>>> print f['composers'].as_hidden() + +>>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False) +>>> print f['composers'].as_hidden() + + + MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. >>> class SongForm(Form): ... name = CharField() @@ -1905,6 +1916,8 @@ returns a list of input. >>> f.clean_data {'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 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