Author: gwilson
Date: 2007-08-01 00:41:32 -0500 (Wed, 01 Aug 2007)
New Revision: 5782

Modified:
   django/trunk/django/newforms/forms.py
   django/trunk/django/newforms/widgets.py
   django/trunk/tests/regressiontests/forms/tests.py
Log:
Fixed #4228 -- Removed hardcoding of `RadioFieldRenderer` in the `RadioSelect` 
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.


Modified: django/trunk/django/newforms/forms.py
===================================================================
--- django/trunk/django/newforms/forms.py       2007-07-31 17:37:11 UTC (rev 
5781)
+++ django/trunk/django/newforms/forms.py       2007-08-01 05:41:32 UTC (rev 
5782)
@@ -232,16 +232,8 @@
         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 @@
         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:

Modified: django/trunk/django/newforms/widgets.py
===================================================================
--- django/trunk/django/newforms/widgets.py     2007-07-31 17:37:11 UTC (rev 
5781)
+++ django/trunk/django/newforms/widgets.py     2007-08-01 05:41:32 UTC (rev 
5782)
@@ -216,7 +216,11 @@
         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 @@
         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,17 +260,31 @@
         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,
         # each of which has a distinct ID. The IDs are made distinct by a "_X"

Modified: django/trunk/tests/regressiontests/forms/tests.py
===================================================================
--- django/trunk/tests/regressiontests/forms/tests.py   2007-07-31 17:37:11 UTC 
(rev 5781)
+++ django/trunk/tests/regressiontests/forms/tests.py   2007-08-01 05:41:32 UTC 
(rev 5782)
@@ -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]


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to