Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fixed #4228 -- Removed hardcoding of `RadioFieldRenderer` in the `Rad…

…ioSelect` Widget so that the display of `RadioSelect`s can be more easily customized. `BoundField.__unicode__` also no longer special cases `RadioSelect` since `RadioSelect.render()` now returns a string like every other Widget.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@5782 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit cdbd5751d3c9579bac7054b45edae11de27171ff 1 parent f27774e
Gary Wilson Jr. gdub authored
21 django/newforms/forms.py
View
@@ -232,16 +232,8 @@ def __init__(self, form, field, name):
self.help_text = field.help_text or ''
def __unicode__(self):
- "Renders this field as an HTML widget."
- # Use the 'widget' attribute on the field to determine which type
- # of HTML widget to use.
- 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 __unicode__() on that
- # object to get its rendered value.
- value = unicode(value)
- return value
+ """Renders this field as an HTML widget."""
+ return self.as_widget()
def _errors(self):
"""
@@ -251,7 +243,14 @@ def _errors(self):
return self.form.errors.get(self.name, ErrorList())
errors = property(_errors)
- def as_widget(self, widget, attrs=None):
+ def as_widget(self, widget=None, attrs=None):
+ """
+ Renders the field by rendering the passed widget, adding any HTML
+ attributes passed as attrs. If no widget is specified, then the
+ field's default widget will be used.
+ """
+ if not widget:
+ widget = self.field.widget
attrs = attrs or {}
auto_id = self.auto_id
if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
33 django/newforms/widgets.py
View
@@ -216,7 +216,11 @@ def value_from_datadict(self, data, name):
return data.get(name, None)
class RadioInput(StrAndUnicode):
- "An object used by RadioFieldRenderer that represents a single <input type='radio'>."
+ """
+ An object used by RadioFieldRenderer that represents a single
+ <input type='radio'>.
+ """
+
def __init__(self, name, value, attrs, choice, index):
self.name, self.value = name, value
self.attrs = attrs
@@ -239,7 +243,10 @@ def tag(self):
return u'<input%s />' % flatatt(final_attrs)
class RadioFieldRenderer(StrAndUnicode):
- "An object used by RadioSelect to enable customization of radio widgets."
+ """
+ An object used by RadioSelect to enable customization of radio widgets.
+ """
+
def __init__(self, name, value, attrs, choices):
self.name, self.value, self.attrs = name, value, attrs
self.choices = choices
@@ -253,16 +260,30 @@ def __getitem__(self, idx):
return RadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
def __unicode__(self):
- "Outputs a <ul> for this set of radio fields."
+ return self.render()
+
+ def render(self):
+ """Outputs a <ul> for this set of radio fields."""
return u'<ul>\n%s\n</ul>' % u'\n'.join([u'<li>%s</li>' % force_unicode(w) for w in self])
class RadioSelect(Select):
- def render(self, name, value, attrs=None, choices=()):
- "Returns a RadioFieldRenderer instance rather than a Unicode string."
+
+ def __init__(self, *args, **kwargs):
+ self.renderer = kwargs.pop('renderer', None)
+ if not self.renderer:
+ self.renderer = RadioFieldRenderer
+ super(RadioSelect, self).__init__(*args, **kwargs)
+
+ def get_renderer(self, name, value, attrs=None, choices=()):
+ """Returns an instance of the renderer."""
if value is None: value = ''
str_value = force_unicode(value) # Normalize to string.
final_attrs = self.build_attrs(attrs)
- return RadioFieldRenderer(name, str_value, final_attrs, list(chain(self.choices, choices)))
+ choices = list(chain(self.choices, choices))
+ return self.renderer(name, str_value, final_attrs, choices)
+
+ def render(self, name, value, attrs=None, choices=()):
+ return self.get_renderer(name, value, attrs, choices).render()
def id_for_label(self, id_):
# RadioSelect is represented by multiple <input type="radio"> fields,
18 tests/regressiontests/forms/tests.py
View
@@ -4,6 +4,7 @@
form_tests = r"""
>>> from django.newforms import *
+>>> from django.newforms.widgets import RadioFieldRenderer
>>> import datetime
>>> import time
>>> import re
@@ -614,11 +615,11 @@
<li><label><input type="radio" name="num" value="5" /> 5</label></li>
</ul>
-The render() method returns a RadioFieldRenderer object, whose str() is a <ul>.
+RadioSelect uses a RadioFieldRenderer to render the individual radio inputs.
You can manipulate that object directly to customize the way the RadioSelect
is rendered.
>>> w = RadioSelect()
->>> r = w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
+>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
>>> for inp in r:
... print inp
<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label>
@@ -644,10 +645,21 @@
beatle J G George False
beatle J R Ringo False
+You can create your own custom renderers for RadioSelect to use.
+>>> class MyRenderer(RadioFieldRenderer):
+... def render(self):
+... return u'<br />\n'.join([unicode(choice) for choice in self])
+>>> w = RadioSelect(renderer=MyRenderer)
+>>> print w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
+<label><input type="radio" name="beatle" value="J" /> John</label><br />
+<label><input type="radio" name="beatle" value="P" /> Paul</label><br />
+<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br />
+<label><input type="radio" name="beatle" value="R" /> Ringo</label>
+
A RadioFieldRenderer object also allows index access to individual RadioInput
objects.
>>> w = RadioSelect()
->>> r = w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
+>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
>>> print r[1]
<label><input type="radio" name="beatle" value="P" /> Paul</label>
>>> print r[0]
Please sign in to comment.
Something went wrong with that request. Please try again.