Fixed #3065 -- newforms: Fixed rendering problem with RadioSelect as a member of a Form. Also fixed some Unicode issues and added unit tests. Thanks for reporting, Derek Hoy

git-svn-id: http://code.djangoproject.com/svn/django/trunk@4106 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-11-26 18:44:58 +00:00
parent 95d19384c0
commit 4a14f2e233
2 changed files with 33 additions and 10 deletions

View File

@ -77,23 +77,23 @@ class Form(object):
def as_table(self): def as_table(self):
"Returns this form rendered as HTML <tr>s -- excluding the <table></table>." "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
return u'\n'.join(['<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) return u'\n'.join([u'<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
def as_ul(self): def as_ul(self):
"Returns this form rendered as HTML <li>s -- excluding the <ul></ul>." "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
return u'\n'.join(['<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()]) return u'\n'.join([u'<li>%s: %s</li>' % (pretty_name(name), BoundField(self, field, name)) for name, field in self.fields.items()])
def as_table_with_errors(self): def as_table_with_errors(self):
"Returns this form rendered as HTML <tr>s, with errors." "Returns this form rendered as HTML <tr>s, with errors."
output = [] output = []
if self.errors().get(NON_FIELD_ERRORS): if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top. # Errors not corresponding to a particular field are displayed at the top.
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]])) output.append(u'<tr><td colspan="2"><ul>%s</ul></td></tr>' % u'\n'.join([u'<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items(): for name, field in self.fields.items():
bf = BoundField(self, field, name) bf = BoundField(self, field, name)
if bf.errors: if bf.errors:
output.append('<tr><td colspan="2"><ul>%s</ul></td></tr>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors])) output.append(u'<tr><td colspan="2"><ul>%s</ul></td></tr>' % u'\n'.join([u'<li>%s</li>' % e for e in bf.errors]))
output.append('<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf)) output.append(u'<tr><td>%s:</td><td>%s</td></tr>' % (pretty_name(name), bf))
return u'\n'.join(output) return u'\n'.join(output)
def as_ul_with_errors(self): def as_ul_with_errors(self):
@ -101,13 +101,13 @@ class Form(object):
output = [] output = []
if self.errors().get(NON_FIELD_ERRORS): if self.errors().get(NON_FIELD_ERRORS):
# Errors not corresponding to a particular field are displayed at the top. # Errors not corresponding to a particular field are displayed at the top.
output.append('<li><ul>%s</ul></li>' % '\n'.join(['<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]])) output.append(u'<li><ul>%s</ul></li>' % u'\n'.join([u'<li>%s</li>' % e for e in self.errors()[NON_FIELD_ERRORS]]))
for name, field in self.fields.items(): for name, field in self.fields.items():
bf = BoundField(self, field, name) bf = BoundField(self, field, name)
line = '<li>' line = u'<li>'
if bf.errors: if bf.errors:
line += '<ul>%s</ul>' % '\n'.join(['<li>%s</li>' % e for e in bf.errors]) line += u'<ul>%s</ul>' % u'\n'.join([u'<li>%s</li>' % e for e in bf.errors])
line += '%s: %s</li>' % (pretty_name(name), bf) line += u'%s: %s</li>' % (pretty_name(name), bf)
output.append(line) output.append(line)
return u'\n'.join(output) return u'\n'.join(output)
@ -153,7 +153,13 @@ class BoundField(object):
"Renders this field as an HTML widget." "Renders this field as an HTML widget."
# Use the 'widget' attribute on the field to determine which type # Use the 'widget' attribute on the field to determine which type
# of HTML widget to use. # of HTML widget to use.
return self.as_widget(self._field.widget) value = self.as_widget(self._field.widget)
if not isinstance(value, basestring):
# Some Widget render() methods -- notably RadioSelect -- return a
# "special" object rather than a string. Call the __str__() on that
# object to get its rendered value.
value = value.__str__()
return value
def _errors(self): def _errors(self):
""" """

View File

@ -955,6 +955,13 @@ u''
<tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr> <tr><td>Last name:</td><td><input type="text" name="last_name" value="Lennon" /></td></tr>
<tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr> <tr><td>Birthday:</td><td><input type="text" name="birthday" value="1940-10-9" /></td></tr>
Unicode values are handled properly.
>>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'})
>>> p.as_table()
u'<tr><td>First name:</td><td><input type="text" name="first_name" value="John" /></td></tr>\n<tr><td>Last name:</td><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /></td></tr>\n<tr><td>Birthday:</td><td><input type="text" name="birthday" /></td></tr>'
>>> p.as_ul()
u'<li>First name: <input type="text" name="first_name" value="John" /></li>\n<li>Last name: <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /></li>\n<li>Birthday: <input type="text" name="birthday" /></li>'
>>> p = Person({'last_name': u'Lennon'}) >>> p = Person({'last_name': u'Lennon'})
>>> p.errors() >>> p.errors()
{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']} {'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
@ -1095,6 +1102,16 @@ For a form with a <select>, use ChoiceField:
<option value="J">Java</option> <option value="J">Java</option>
</select> </select>
>>> class FrameworkForm(Form):
... name = CharField()
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect)
>>> f = FrameworkForm()
>>> print f['language']
<ul>
<li><label><input type="radio" name="language" value="P" /> Python</label></li>
<li><label><input type="radio" name="language" value="J" /> Java</label></li>
</ul>
MultipleChoiceField is a special case, as its data is required to be a list: MultipleChoiceField is a special case, as its data is required to be a list:
>>> class SongForm(Form): >>> class SongForm(Form):
... name = CharField() ... name = CharField()