Ticket #27487: #27487.diff

File #27487.diff, 26.7 KB (added by Adonys Alea Boffill, 7 years ago)

Fixed add related object in admin popup for checkbox/radio

  • django/contrib/admin/static/admin/css/widgets.css

    diff --git a/django/contrib/admin/static/admin/css/widgets.css b/django/contrib/admin/static/admin/css/widgets.css
    index d3bd67a..491b18b 100644
    a b ul.timelist, .timelist li {  
    546546    overflow: hidden;  /* clear floated contents */
    547547}
    548548
     549.related-widget-wrapper .empty-choice {
     550    display: none;
     551}
     552
    549553.related-widget-wrapper-link {
    550554    opacity: 0.3;
    551555}
  • django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js

    diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
    index 3fb1e52..5f9134f 100644
    a b  
    8787                    elem.value = newId;
    8888                }
    8989            }
     90            else if (elemName === 'UL') {
     91                // For this case the result won't be appended to a simple html input field, we have a
     92                // list (<ul></ul>) and we need to append a new item. An empty item is expected as the
     93                // first item of the list, with the format specified. Finally, the empty item will be
     94                // used as template in order to replace on it the new information.
     95                if (elem.firstChild.className.includes('empty-choice')) {
     96                    var itemTemplate = elem.firstChild.outerHTML,  // Get template html string
     97                        inputIdRegExp = new RegExp(elem.id + '_-1', 'g'),  // RegExp to replace the input field Id
     98                        inputId = elem.id + '_' + (elem.children.length - 1);  // New input Id
     99
     100                    itemTemplate = itemTemplate.replace(/empty-choice/g, '');  // Remove 'empty-choice' class
     101                    itemTemplate = itemTemplate.replace(inputIdRegExp, inputId);  // Replace the input Id
     102                    itemTemplate = itemTemplate.replace('value="#"', 'value="' + newId + '"');  // Replace input value
     103                    itemTemplate = itemTemplate.replace('--EMPTY LABEL--', newRepr);  // Replace label value
     104                    // append new item to the list
     105                    elem.innerHTML = elem.innerHTML + itemTemplate;
     106                }
     107            }
    90108            // Trigger a change event to update related links if required.
    91109            $(elem).trigger('change');
    92110        } else {
  • django/forms/widgets.py

    diff --git a/django/forms/widgets.py b/django/forms/widgets.py
    index 7c7e2c9..f75b27f 100644
    a b class CheckboxChoiceInput(ChoiceInput):  
    701701@python_2_unicode_compatible
    702702class ChoiceFieldRenderer(object):
    703703    """
    704     An object used by RadioSelect to enable customization of radio widgets.
     704    An object used by RadioSelect and CheckboxSelectMultiple to enable customization of widgets.
    705705    """
    706706
    707707    choice_input_class = None
    708708    outer_html = '<ul{id_attr}>{content}</ul>'
    709     inner_html = '<li>{choice_value}{sub_widgets}</li>'
     709    inner_html = '<li{class_attr}>{choice_value}{sub_widgets}</li>'
    710710
    711711    def __init__(self, name, value, attrs, choices):
    712712        self.name = name
    class ChoiceFieldRenderer(object):  
    729729        Outputs a <ul> for this set of choice fields.
    730730        If an id was given to the field, it is applied to the <ul> (each
    731731        item in the list will get an id of `$id_$i`).
     732        The first item of the list will be an empty item.
    732733        """
    733734        id_ = self.attrs.get('id')
    734735        output = []
     736
     737        def append_inner_item_choice(item_choice, index, class_attr=""):
     738            w = self.choice_input_class(self.name, self.value, self.attrs.copy(), item_choice, index)
     739            output.append(
     740                format_html(self.inner_html, class_attr=class_attr, choice_value=force_text(w), sub_widgets='')
     741            )
     742
     743        # append empty item choice
     744        append_inner_item_choice(
     745            ('#', '--EMPTY LABEL--'),  # empty choice
     746            -1,  # index
     747            format_html(' class="{}"', 'empty-choice')  # classes for empty item choice
     748        )
     749
    735750        for i, choice in enumerate(self.choices):
    736751            choice_value, choice_label = choice
    737752            if isinstance(choice_label, (tuple, list)):
    class ChoiceFieldRenderer(object):  
    746761                )
    747762                sub_ul_renderer.choice_input_class = self.choice_input_class
    748763                output.append(format_html(
    749                     self.inner_html, choice_value=choice_value,
     764                    self.inner_html, class_attr='', choice_value=choice_value,
    750765                    sub_widgets=sub_ul_renderer.render(),
    751766                ))
    752767            else:
    753                 w = self.choice_input_class(self.name, self.value, self.attrs.copy(), choice, i)
    754                 output.append(format_html(self.inner_html, choice_value=force_text(w), sub_widgets=''))
     768                append_inner_item_choice(choice, i)
     769
    755770        return format_html(
    756771            self.outer_html,
    757772            id_attr=format_html(' id="{}"', id_) if id_ else '',
  • js_tests/admin/RelatedObjectLookups.test.js

    diff --git a/js_tests/admin/RelatedObjectLookups.test.js b/js_tests/admin/RelatedObjectLookups.test.js
    index 83071ed..3877a50 100644
    a b  
    33/* eslint global-strict: 0, strict: 0 */
    44'use strict';
    55
    6 module('admin.RelatedObjectLookups');
     6module('admin.RelatedObjectLookups', {
     7    setup: function() {
     8        this.win = {name: 'id_teacher', close: function() {}};
     9    }
     10});
    711
    812test('id_to_windowname', function(assert) {
    913    assert.equal(id_to_windowname('.test'), '__dot__test');
    test('windowname_to_id', function(assert) {  
    1418    assert.equal(windowname_to_id('__dot__test'), '.test');
    1519    assert.equal(windowname_to_id('misc__dash__test'), 'misc-test');
    1620});
     21
     22test('dismissAddRelatedObjectPopup/Select', function(assert) {
     23    var $ = django.jQuery;
     24    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     25    $('<select id="id_teacher" name="teacher"></select>').appendTo('div.related-widget-wrapper');
     26    $('<option value="" selected="">---------</option>').appendTo('#id_teacher');
     27
     28    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
     29    assert.equal($('#id_teacher').find('option').length, 2);
     30    assert.equal($('#id_teacher').find('option').last().text(), 'Alex');
     31});
     32
     33test('dismissAddRelatedObjectPopup/SelectMultiple', function(assert) {
     34    var $ = django.jQuery;
     35    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     36    $('<select multiple="multiple" id="id_teacher" name="teacher"></select>').appendTo('div.related-widget-wrapper');
     37
     38    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
     39    assert.equal($('#id_teacher').find('option').length, 1);
     40    assert.equal($('#id_teacher').find('option').first().text(), 'Alex');
     41
     42    dismissAddRelatedObjectPopup(this.win, '2', 'Alan');
     43    assert.equal($('#id_teacher').find('option').length, 2);
     44    assert.equal($('#id_teacher').find('option').last().text(), 'Alan');
     45});
     46
     47test('dismissAddRelatedObjectPopup/TextInput', function(assert) {
     48    var $ = django.jQuery;
     49    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     50    $('<input id="id_teacher" name="teacher" type="text" value="">').appendTo('div.related-widget-wrapper');
     51
     52    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
     53    assert.equal($('#id_teacher').val(), '1');
     54
     55    dismissAddRelatedObjectPopup(this.win, '2', 'Alan');
     56    assert.equal($('#id_teacher').val(), '2');
     57});
     58
     59test('dismissAddRelatedObjectPopup/TextInput.vManyToManyRawIdAdminField', function(assert) {
     60    var $ = django.jQuery;
     61    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     62    $('<input id="id_teacher" name="teacher" type="text" value="" class="vManyToManyRawIdAdminField">').appendTo(
     63        'div.related-widget-wrapper'
     64    );
     65
     66    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
     67    assert.equal($('#id_teacher').val(), '1');
     68
     69    dismissAddRelatedObjectPopup(this.win, '2', 'Alan');
     70    assert.equal($('#id_teacher').val(), '1,2');
     71});
     72
     73test('dismissAddRelatedObjectPopup/CheckboxSelectMultiple', function(assert) {
     74    var $ = django.jQuery;
     75    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     76    $('<ul id="id_books"></ul>').appendTo('div.related-widget-wrapper');
     77    $('<li class="empty-choice"></li>').appendTo('#id_books');
     78    $('<label for="id_books_-1"></label>').appendTo('li.empty-choice');
     79    $('li label').html('<input id="id_books_-1" name="books" type="checkbox" value="#">--EMPTY LABEL--');
     80
     81    this.win = $.extend(this.win, {name: 'id_books'});
     82
     83    // add the first item
     84    dismissAddRelatedObjectPopup(this.win, '1', 'Book1');
     85    assert.equal($('#id_books').find('li').length, 2);
     86    assert.notOk($('#id_books').find('li').last().hasClass("empty-choice"));
     87    assert.equal($('input#id_books_0').length, 1);
     88    assert.equal($('input#id_books_0').val(), 1);
     89    assert.equal($('#id_books').find('li').last().find('label').text(), 'Book1');
     90    assert.equal($('#id_books').find('input').last()[0].type, "checkbox");
     91
     92    // add the other item
     93    dismissAddRelatedObjectPopup(this.win, '2', 'Book2');
     94    assert.equal($('#id_books').find('li').length, 3);
     95    assert.notOk($('#id_books').find('li').last().hasClass("empty-choice"));
     96    assert.equal($('input#id_books_1').length, 1);
     97    assert.equal($('input#id_books_1').val(), 2);
     98    assert.equal($('#id_books').find('li').last().find('label').text(), 'Book2');
     99    assert.equal($('#id_books').find('input').last()[0].type, "checkbox");
     100});
     101
     102test('dismissAddRelatedObjectPopup/RadioSelect', function(assert) {
     103    var $ = django.jQuery;
     104    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
     105    $('<ul id="id_books"></ul>').appendTo('div.related-widget-wrapper');
     106    $('<li class="empty-choice"></li>').appendTo('#id_books');
     107    $('<label for="id_books_-1"></label>').appendTo('li.empty-choice');
     108    $('li label').html('<input id="id_books_-1" name="books" type="radio" value="#">--EMPTY LABEL--');
     109
     110    this.win = $.extend(this.win, {name: 'id_books'});
     111
     112    // add the first item
     113    dismissAddRelatedObjectPopup(this.win, '1', 'Book1');
     114    assert.equal($('#id_books').find('li').length, 2);
     115    assert.notOk($('#id_books').find('li').last().hasClass("empty-choice"));
     116    assert.equal($('input#id_books_0').length, 1);
     117    assert.equal($('input#id_books_0').val(), 1);
     118    assert.equal($('#id_books').find('li').last().find('label').text(), 'Book1');
     119    assert.equal($('#id_books').find('input').last()[0].type, "radio");
     120
     121    // add the other item
     122    dismissAddRelatedObjectPopup(this.win, '2', 'Book2');
     123    assert.equal($('#id_books').find('li').length, 3);
     124    assert.notOk($('#id_books').find('li').last().hasClass("empty-choice"));
     125    assert.equal($('input#id_books_1').length, 1);
     126    assert.equal($('input#id_books_1').val(), 2);
     127    assert.equal($('#id_books').find('li').last().find('label').text(), 'Book2');
     128    assert.equal($('#id_books').find('input').last()[0].type, "radio");
     129});
  • tests/forms_tests/tests/test_forms.py

    diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
    index 8007ad8..0ec3d3f 100644
    a b class FormsTestCase(SimpleTestCase):  
    584584
    585585        f = FrameworkForm(auto_id=False)
    586586        self.assertHTMLEqual(str(f['language']), """<ul>
     587<li class="empty-choice"><label><input type="radio" name="language" value="#" required /> --EMPTY LABEL--</label></li>
    587588<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
    588589<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
    589590</ul>""")
    590591        self.assertHTMLEqual(f.as_table(), """<tr><th>Name:</th><td><input type="text" name="name" required /></td></tr>
    591592<tr><th>Language:</th><td><ul>
     593<li class="empty-choice"><label><input type="radio" name="language" value="#" required /> --EMPTY LABEL--</label></li>
    592594<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
    593595<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
    594596</ul></td></tr>""")
    595597        self.assertHTMLEqual(f.as_ul(), """<li>Name: <input type="text" name="name" required /></li>
    596598<li>Language: <ul>
     599<li class="empty-choice"><label><input type="radio" name="language" value="#" required /> --EMPTY LABEL--</label></li>
    597600<li><label><input type="radio" name="language" value="P" required /> Python</label></li>
    598601<li><label><input type="radio" name="language" value="J" required /> Java</label></li>
    599602</ul></li>""")
    class FormsTestCase(SimpleTestCase):  
    605608        self.assertHTMLEqual(
    606609            str(f['language']),
    607610            """<ul id="id_language">
     611<li class="empty-choice"><label for="id_language_-1">
     612<input type="radio" id="id_language_-1" value="#" name="language" required /> --EMPTY LABEL--</label></li>
    608613<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
    609614Python</label></li>
    610615<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
    Java</label></li>  
    619624            f.as_table(),
    620625            """<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" required /></td></tr>
    621626<tr><th><label for="id_language_0">Language:</label></th><td><ul id="id_language">
     627<li class="empty-choice"><label for="id_language_-1">
     628<input type="radio" id="id_language_-1" value="#" name="language" required />--EMPTY LABEL--</label></li>
    622629<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
    623630Python</label></li>
    624631<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
    Java</label></li>  
    629636            f.as_ul(),
    630637            """<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></li>
    631638<li><label for="id_language_0">Language:</label> <ul id="id_language">
     639<li class="empty-choice"><label for="id_language_-1">
     640<input type="radio" id="id_language_-1" value="#" name="language" required />--EMPTY LABEL--</label></li>
    632641<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
    633642Python</label></li>
    634643<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
    Java</label></li>  
    639648            f.as_p(),
    640649            """<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></p>
    641650<p><label for="id_language_0">Language:</label> <ul id="id_language">
     651<li class="empty-choice"><label for="id_language_-1">
     652<input type="radio" id="id_language_-1" value="#" name="language" required />--EMPTY LABEL--</label></li>
    642653<li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
    643654Python</label></li>
    644655<li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
    Java</label></li>  
    808819
    809820        f = SongForm(auto_id=False)
    810821        self.assertHTMLEqual(str(f['composers']), """<ul>
     822<li class="empty-choice"><label><input type="checkbox" name="composers" value="#" /> --EMPTY LABEL--</label></li>
    811823<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li>
    812824<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
    813825</ul>""")
    814826        f = SongForm({'composers': ['J']}, auto_id=False)
    815827        self.assertHTMLEqual(str(f['composers']), """<ul>
     828<li class="empty-choice"><label><input type="checkbox" name="composers" value="#" /> --EMPTY LABEL--</label></li>
    816829<li><label><input checked type="checkbox" name="composers" value="J" /> John Lennon</label></li>
    817830<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
    818831</ul>""")
    819832        f = SongForm({'composers': ['J', 'P']}, auto_id=False)
    820833        self.assertHTMLEqual(str(f['composers']), """<ul>
     834<li class="empty-choice"><label><input type="checkbox" name="composers" value="#" /> --EMPTY LABEL--</label></li>
    821835<li><label><input checked type="checkbox" name="composers" value="J" /> John Lennon</label></li>
    822836<li><label><input checked type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
    823837</ul>""")
    Java</label></li>  
    843857        self.assertHTMLEqual(
    844858            str(f['composers']),
    845859            """<ul id="composers_id">
     860<li class="empty-choice"><label for="composers_id_-1">
     861<input type="checkbox" name="composers" value="#" id="composers_id_-1" /> --EMPTY LABEL--</label></li>
    846862<li><label for="composers_id_0">
    847863<input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li>
    848864<li><label for="composers_id_1">
  • tests/forms_tests/tests/test_i18n.py

    diff --git a/tests/forms_tests/tests/test_i18n.py b/tests/forms_tests/tests/test_i18n.py
    index 56225e0..956f4ec 100644
    a b class FormsI18nTests(SimpleTestCase):  
    6060            f.as_p(),
    6161            '<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
    6262            '<ul id="id_somechoice">\n'
     63            '<li class="empty-choice"><label for="id_somechoice_-1">'
     64            '<input type="radio" id="id_somechoice_-1" value="#" name="somechoice" required /> '
     65            '--EMPTY LABEL--</label></li>\n'
    6366            '<li><label for="id_somechoice_0">'
    6467            '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
    6568            'En tied\xe4</label></li>\n'
    class FormsI18nTests(SimpleTestCase):  
    7982                '\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c'
    8083                '\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n'
    8184                '<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
    82                 ' <ul id="id_somechoice">\n<li><label for="id_somechoice_0">'
     85                ' <ul id="id_somechoice">\n<li class="empty-choice"><label for="id_somechoice_-1">'
     86                '<input type="radio" id="id_somechoice_-1" value="#" name="somechoice" required /> '
     87                '--EMPTY LABEL--</label></li>\n'
     88                '<li><label for="id_somechoice_0">'
    8389                '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
    8490                'En tied\xe4</label></li>\n'
    8591                '<li><label for="id_somechoice_1">'
  • tests/forms_tests/tests/test_widgets.py

    diff --git a/tests/forms_tests/tests/test_widgets.py b/tests/forms_tests/tests/test_widgets.py
    index 7ea2b35..b33248d 100644
    a b beatle J R Ringo False""")  
    118118        self.assertHTMLEqual(
    119119            output,
    120120            """<div id="bar">
     121<p><label for="bar_-1"><input type="radio" id="bar_-1" value="#" name="beatle" /> --EMPTY LABEL--</label></p>
    121122<p><label for="bar_0"><input checked type="radio" id="bar_0" value="J" name="beatle" /> John</label></p>
    122123<p><label for="bar_1"><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></p>
    123124<p><label for="bar_2"><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></p>
  • tests/forms_tests/widget_tests/test_checkboxselectmultiple.py

    diff --git a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py
    index 27e8705..07cef1f 100644
    a b class CheckboxSelectMultipleTest(WidgetTest):  
    99    def test_render_value(self):
    1010        self.check_html(self.widget(choices=self.beatles), 'beatles', ['J'], html=(
    1111            """<ul>
     12            <li class="empty-choice">
     13            <label><input type="checkbox" name="beatles" value="#" /> --EMPTY LABEL--</label>
     14            </li>
    1215            <li><label><input checked type="checkbox" name="beatles" value="J" /> John</label></li>
    1316            <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
    1417            <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
    class CheckboxSelectMultipleTest(WidgetTest):  
    1922    def test_render_value_multiple(self):
    2023        self.check_html(self.widget(choices=self.beatles), 'beatles', ['J', 'P'], html=(
    2124            """<ul>
     25            <li class="empty-choice">
     26            <label><input type="checkbox" name="beatles" value="#" /> --EMPTY LABEL--</label>
     27            </li>
    2228            <li><label><input checked type="checkbox" name="beatles" value="J" /> John</label></li>
    2329            <li><label><input checked type="checkbox" name="beatles" value="P" /> Paul</label></li>
    2430            <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
    class CheckboxSelectMultipleTest(WidgetTest):  
    3238        """
    3339        self.check_html(self.widget(choices=self.beatles), 'beatles', None, html=(
    3440            """<ul>
     41            <li class="empty-choice">
     42            <label><input type="checkbox" name="beatles" value="#" /> --EMPTY LABEL--</label>
     43            </li>
    3544            <li><label><input type="checkbox" name="beatles" value="J" /> John</label></li>
    3645            <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
    3746            <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
    class CheckboxSelectMultipleTest(WidgetTest):  
    4756        )
    4857        html = """
    4958        <ul id="media">
     59        <li class="empty-choice">
     60        <label for="media_-1">
     61        <input id="media_-1" name="nestchoice" type="checkbox" value="#" /> --EMPTY LABEL--
     62        </label>
     63        </li>
    5064        <li>
    5165        <label for="media_0"><input id="media_0" name="nestchoice" type="checkbox" value="unknown" /> Unknown</label>
    5266        </li>
    5367        <li>Audio<ul id="media_1">
     68        <li class="empty-choice">
     69        <label for="media_1_-1">
     70        <input id="media_1_-1" name="nestchoice" type="checkbox" value="#" /> --EMPTY LABEL--
     71        </label>
     72        </li>
    5473        <li>
    5574        <label for="media_1_0">
    5675        <input checked id="media_1_0" name="nestchoice" type="checkbox" value="vinyl" /> Vinyl
    class CheckboxSelectMultipleTest(WidgetTest):  
    6180        </li>
    6281        </ul></li>
    6382        <li>Video<ul id="media_2">
     83        <li class="empty-choice">
     84        <label for="media_2_-1">
     85        <input id="media_2_-1" name="nestchoice" type="checkbox" value="#" /> --EMPTY LABEL--
     86        </label>
     87        </li>
    6488        <li>
    6589        <label for="media_2_0"><input id="media_2_0" name="nestchoice" type="checkbox" value="vhs" /> VHS</label>
    6690        </li>
    class CheckboxSelectMultipleTest(WidgetTest):  
    84108        choices = [('a', 'A'), ('b', 'B'), ('c', 'C')]
    85109        html = """
    86110        <ul id="abc">
     111        <li class="empty-choice">
     112        <label for="abc_-1"><input type="checkbox" name="letters" value="#" id="abc_-1" /> --EMPTY LABEL--</label>
     113        </li>
    87114        <li>
    88115        <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
    89116        </li>
    class CheckboxSelectMultipleTest(WidgetTest):  
    102129        widget = CheckboxSelectMultiple(attrs={'id': 'abc'}, choices=[('a', 'A'), ('b', 'B'), ('c', 'C')])
    103130        html = """
    104131        <ul id="abc">
     132        <li  class="empty-choice">
     133        <label for="abc_-1"><input type="checkbox" name="letters" value="#" id="abc_-1" /> --EMPTY LABEL--</label>
     134        </li>
    105135        <li>
    106136        <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
    107137        </li>
  • tests/forms_tests/widget_tests/test_radioselect.py

    diff --git a/tests/forms_tests/widget_tests/test_radioselect.py b/tests/forms_tests/widget_tests/test_radioselect.py
    index fea26ce..c44cb4c 100644
    a b class RadioSelectTest(WidgetTest):  
    99    def test_render(self):
    1010        self.check_html(self.widget(choices=self.beatles), 'beatle', 'J', html=(
    1111            """<ul>
     12            <li class="empty-choice"><label><input type="radio" name="beatle" value="#" /> --EMPTY LABEL--</label></li>
    1213            <li><label><input checked type="radio" name="beatle" value="J" /> John</label></li>
    1314            <li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
    1415            <li><label><input type="radio" name="beatle" value="G" /> George</label></li>
    class RadioSelectTest(WidgetTest):  
    2425        )
    2526        html = """
    2627        <ul id="media">
     28        <li class="empty-choice">
     29        <label for="media_-1"><input id="media_-1" name="nestchoice" type="radio" value="#" /> --EMPTY LABEL--</label>
     30        </li>
    2731        <li>
    2832        <label for="media_0"><input id="media_0" name="nestchoice" type="radio" value="unknown" /> Unknown</label>
    2933        </li>
    3034        <li>Audio<ul id="media_1">
     35        <li class="empty-choice">
     36        <label for="media_1_-1">
     37        <input id="media_1_-1" name="nestchoice" type="radio" value="#" /> --EMPTY LABEL--
     38        </label>
     39        </li>
    3140        <li>
    3241        <label for="media_1_0"><input id="media_1_0" name="nestchoice" type="radio" value="vinyl" /> Vinyl</label>
    3342        </li>
    3443        <li><label for="media_1_1"><input id="media_1_1" name="nestchoice" type="radio" value="cd" /> CD</label></li>
    3544        </ul></li>
    3645        <li>Video<ul id="media_2">
     46        <li class="empty-choice">
     47        <label for="media_2_-1">
     48        <input id="media_2_-1" name="nestchoice" type="radio" value="#" /> --EMPTY LABEL--
     49        </label>
     50        </li>
    3751        <li><label for="media_2_0"><input id="media_2_0" name="nestchoice" type="radio" value="vhs" /> VHS</label></li>
    3852        <li>
    3953        <label for="media_2_1">
    class RadioSelectTest(WidgetTest):  
    5670        widget = RadioSelect(attrs={'id': 'foo'}, choices=self.beatles)
    5771        html = """
    5872        <ul id="foo">
     73        <li class="empty-choice">
     74        <label for="foo_-1"><input type="radio" id="foo_-1" value="#" name="beatle" /> --EMPTY LABEL--</label>
     75        </li>
    5976        <li>
    6077        <label for="foo_0"><input checked type="radio" id="foo_0" value="J" name="beatle" /> John</label>
    6178        </li>
    class RadioSelectTest(WidgetTest):  
    7390        """
    7491        html = """
    7592        <ul id="bar">
     93        <li class="empty-choice">
     94        <label for="bar_-1"><input type="radio" id="bar_-1" value="#" name="beatle" /> --EMPTY LABEL--</label>
     95        </li>
    7696        <li>
    7797        <label for="bar_0"><input checked type="radio" id="bar_0" value="J" name="beatle" /> John</label>
    7898        </li>
Back to Top