mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #4228 -- Removed hardcoding of RadioFieldRenderer in the RadioSelect Widget so that the display of RadioSelects 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
This commit is contained in:
		| @@ -232,16 +232,8 @@ class BoundField(StrAndUnicode): | ||||
|         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 @@ class BoundField(StrAndUnicode): | ||||
|         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: | ||||
|   | ||||
| @@ -216,7 +216,11 @@ class SelectMultiple(Widget): | ||||
|         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 @@ class RadioInput(StrAndUnicode): | ||||
|         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 @@ class RadioFieldRenderer(StrAndUnicode): | ||||
|         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, | ||||
|   | ||||
| @@ -4,6 +4,7 @@ from regressions import regression_tests | ||||
|  | ||||
| form_tests = r""" | ||||
| >>> from django.newforms import * | ||||
| >>> from django.newforms.widgets import RadioFieldRenderer | ||||
| >>> import datetime | ||||
| >>> import time | ||||
| >>> import re | ||||
| @@ -614,11 +615,11 @@ If 'choices' is passed to both the constructor and render(), then they'll both b | ||||
| <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 P Paul False | ||||
| 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] | ||||
|   | ||||
		Reference in New Issue
	
	Block a user