Changed BoundField.subwidgets() to return SubWidget objects instead of rendered strings. This means we can access individual radio buttons' properties in the template (see new docs)
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17175 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
0920165bc2
commit
08bec4fbc1
|
@ -418,7 +418,13 @@ class BoundField(StrAndUnicode):
|
|||
iterate over individual radio buttons in a template.
|
||||
"""
|
||||
for subwidget in self.field.widget.subwidgets(self.html_name, self.value()):
|
||||
yield self.as_widget(subwidget)
|
||||
yield subwidget
|
||||
|
||||
def __len__(self):
|
||||
return len(list(self.__iter__()))
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return list(self.__iter__())[idx]
|
||||
|
||||
def _errors(self):
|
||||
"""
|
||||
|
|
|
@ -137,6 +137,22 @@ class MediaDefiningClass(type):
|
|||
new_class.media = media_property(new_class)
|
||||
return new_class
|
||||
|
||||
class SubWidget(StrAndUnicode):
|
||||
"""
|
||||
Some widgets are made of multiple HTML elements -- namely, RadioSelect.
|
||||
This is a class that represents the "inner" HTML element of a widget.
|
||||
"""
|
||||
def __init__(self, parent_widget, name, value, attrs, choices):
|
||||
self.parent_widget = parent_widget
|
||||
self.name, self.value = name, value
|
||||
self.attrs, self.choices = attrs, choices
|
||||
|
||||
def __unicode__(self):
|
||||
args = [self.name, self.value, self.attrs]
|
||||
if self.choices:
|
||||
args.append(self.choices)
|
||||
return self.parent_widget.render(*args)
|
||||
|
||||
class Widget(object):
|
||||
__metaclass__ = MediaDefiningClass
|
||||
is_hidden = False # Determines whether this corresponds to an <input type="hidden">.
|
||||
|
@ -163,7 +179,7 @@ class Widget(object):
|
|||
|
||||
Arguments are the same as for render().
|
||||
"""
|
||||
yield self
|
||||
yield SubWidget(self, name, value, attrs, choices)
|
||||
|
||||
def render(self, name, value, attrs=None):
|
||||
"""
|
||||
|
@ -623,7 +639,7 @@ class SelectMultiple(Select):
|
|||
data_set = set([force_unicode(value) for value in data])
|
||||
return data_set != initial_set
|
||||
|
||||
class RadioInput(StrAndUnicode):
|
||||
class RadioInput(SubWidget):
|
||||
"""
|
||||
An object used by RadioFieldRenderer that represents a single
|
||||
<input type='radio'>.
|
||||
|
|
|
@ -386,8 +386,41 @@ commonly used groups of widgets:
|
|||
<label><input type="radio" name="beatles" value="ringo" /> Ringo</label>
|
||||
</div>
|
||||
|
||||
If you decide not to loop over the radio buttons, they'll be output in a
|
||||
``<ul>`` with ``<li>`` tags, as above.
|
||||
That included the ``<label>`` tags. To get more granular, you can use each
|
||||
radio button's ``tag`` and ``choice_label`` attributes. For example, this template...
|
||||
|
||||
.. code-block:: html+django
|
||||
|
||||
{% for radio in myform.beatles %}
|
||||
<label>
|
||||
{{ radio.choice_label }}
|
||||
<span class="radio">{{ radio.tag }}</span>
|
||||
</label>
|
||||
{% endfor %}
|
||||
|
||||
...will result in the following HTML:
|
||||
|
||||
.. code-block:: html
|
||||
|
||||
<label>
|
||||
John
|
||||
<span class="radio"><input type="radio" name="beatles" value="john" /></span>
|
||||
</label>
|
||||
<label>
|
||||
Paul
|
||||
<span class="radio"><input type="radio" name="beatles" value="paul" /></span>
|
||||
</label>
|
||||
<label>
|
||||
George
|
||||
<span class="radio"><input type="radio" name="beatles" value="george" /></span>
|
||||
</label>
|
||||
<label>
|
||||
Ringo
|
||||
<span class="radio"><input type="radio" name="beatles" value="ringo" /></span>
|
||||
</label>
|
||||
|
||||
If you decide not to loop over the radio buttons -- e.g., if your template simply includes
|
||||
``{{ myform.beatles }}`` -- they'll be output in a ``<ul>`` with ``<li>`` tags, as above.
|
||||
|
||||
``CheckboxSelectMultiple``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
@ -439,7 +439,7 @@ class FormsTestCase(TestCase):
|
|||
name = ChoiceField(choices=[('john', 'John'), ('paul', 'Paul'), ('george', 'George'), ('ringo', 'Ringo')], widget=RadioSelect)
|
||||
|
||||
f = BeatleForm(auto_id=False)
|
||||
self.assertEqual('\n'.join(list(f['name'])), """<label><input type="radio" name="name" value="john" /> John</label>
|
||||
self.assertEqual('\n'.join([str(bf) for bf in f['name']]), """<label><input type="radio" name="name" value="john" /> John</label>
|
||||
<label><input type="radio" name="name" value="paul" /> Paul</label>
|
||||
<label><input type="radio" name="name" value="george" /> George</label>
|
||||
<label><input type="radio" name="name" value="ringo" /> Ringo</label>""")
|
||||
|
@ -454,7 +454,7 @@ class FormsTestCase(TestCase):
|
|||
name = CharField()
|
||||
|
||||
f = BeatleForm(auto_id=False)
|
||||
self.assertEqual('\n'.join(list(f['name'])), u'<input type="text" name="name" />')
|
||||
self.assertEqual('\n'.join([str(bf) for bf in f['name']]), u'<input type="text" name="name" />')
|
||||
|
||||
def test_forms_with_multiple_choice(self):
|
||||
# MultipleChoiceField is a special case, as its data is required to be a list:
|
||||
|
|
Loading…
Reference in New Issue