diff --git a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
index 3fb1e52..9f68bc1 100644
--- a/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
+++ b/django/contrib/admin/static/admin/js/admin/RelatedObjectLookups.js
@@ -86,6 +86,67 @@
                 } else {
                     elem.value = newId;
                 }
+            } else if (elemName === 'UL') {
+                var numberOfItems = elem.children.length,
+                    // If the input field is wrapped into a label.
+                    wrapLabel = (String(elem.getAttribute('data-wrap-label')).toLowerCase() == "true"),
+                    // Multiple selection or not.
+                    multiple = (String(elem.getAttribute('data-multiple')).toLowerCase() == "true");
+
+                if (numberOfItems > 0) {
+                    if (!multiple) {
+                        // Remove previous input checked, the new item will marked as checked.
+                        elem.querySelector('input:checked').checked = false;
+                    }
+                    // Clone an item and include this as the final item of the UL list.
+                    // The clone will be the new item and their information will be
+                    // replaced with the received data.
+                    elem.appendChild(elem.lastElementChild.cloneNode(true));
+                    // newItem's var is the new copy, is necessary to get a new instance to work
+                    // with it in order to avoid to modify the cloned item.
+                    var newItem = elem.lastElementChild,
+                        newItemInput = newItem.getElementsByTagName('input')[0];
+
+                    newItemInput.value = newId;
+                    newItemInput.setAttribute('id', elem.id + '_' + numberOfItems);
+                    // Mark the new item's input as checked.
+                    newItemInput.checked = true;
+
+                    if (wrapLabel) {
+                        var newItemLabel = newItem.getElementsByTagName('label')[0];
+                        newItemLabel.lastChild.textContent = ' ' + newRepr;
+                        newItemLabel.setAttribute('for', elem.id + '_' + numberOfItems);
+                    }
+                } else {
+                    // The UL list is empty, then is necessary to build the new item.
+                    var newItem = document.createElement('li'),
+                        newItemInput = document.createElement('input');
+
+                    newItemInput.setAttribute('type', (multiple) ? 'checkbox' : 'radio');
+                    // The elem.id is composed by 'id_' and the name of the related field.
+                    // Example: 'id_books', is only necessary to remove 'id_' to get the
+                    // name of the field.
+                    newItemInput.setAttribute('name', elem.id.replace('id_', ''));
+                    newItemInput.setAttribute('id', elem.id + '_0');
+                    // Mark the new item's input as checked.
+                    newItemInput.checked = true;
+                    newItemInput.value = newId;
+
+                    if (wrapLabel) {
+                        var newItemLabel = document.createElement('label');
+                        newItemLabel.textContent = ' ' + newRepr;
+                        newItemLabel.setAttribute('for', elem.id + '_0');
+                        // Insert input into label.
+                        newItemLabel.insertBefore(newItemInput, newItemLabel.firstChild);
+                        // Append input wrapped into new item.
+                        newItem.appendChild(newItemLabel);
+                    } else {
+                        // Append input no wrapped into new item.
+                        newItem.appendChild(newItemInput);
+                    }
+                    // Append new item into UL list.
+                    elem.appendChild(newItem);
+                }
             }
             // Trigger a change event to update related links if required.
             $(elem).trigger('change');
diff --git a/django/forms/jinja2/django/forms/widgets/multiple_input.html b/django/forms/jinja2/django/forms/widgets/multiple_input.html
index be3d449..324f495 100644
--- a/django/forms/jinja2/django/forms/widgets/multiple_input.html
+++ b/django/forms/jinja2/django/forms/widgets/multiple_input.html
@@ -1,4 +1,4 @@
-{% set id = widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
+{% set id = widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %} data-wrap-label="{{ wrap_label|lower }}" data-multiple="{{ multiple|lower }}">{% for group, options, index in widget.optgroups %}{% if group %}
   <li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}{% endif %}">{% endif %}{% for widget in options %}
     <li>{% include widget.template_name %}</li>{% endfor %}{% if group %}
   </ul></li>{% endif %}{% endfor %}
diff --git a/django/forms/templates/django/forms/widgets/multiple_input.html b/django/forms/templates/django/forms/widgets/multiple_input.html
index 60282ff..55881ba 100644
--- a/django/forms/templates/django/forms/widgets/multiple_input.html
+++ b/django/forms/templates/django/forms/widgets/multiple_input.html
@@ -1,4 +1,4 @@
-{% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %}>{% for group, options, index in widget.optgroups %}{% if group %}
+{% with id=widget.attrs.id %}<ul{% if id %} id="{{ id }}"{% endif %} data-wrap-label="{{ wrap_label|lower }}" data-multiple="{{ multiple|lower }}">{% for group, options, index in widget.optgroups %}{% if group %}
   <li>{{ group }}<ul{% if id %} id="{{ id }}_{{ index }}{% endif %}">{% endif %}{% for option in options %}
     <li>{% include option.template_name with widget=option %}</li>{% endfor %}{% if group %}
   </ul></li>{% endif %}{% endfor %}
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index 4f028d3..5aed91a 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -626,6 +626,7 @@ class ChoiceWidget(Widget):
         context = super(ChoiceWidget, self).get_context(name, value, attrs)
         context['widget']['optgroups'] = self.optgroups(name, context['widget']['value'], attrs)
         context['wrap_label'] = True
+        context['multiple'] = self.allow_multiple_selected
         return context
 
     def id_for_label(self, id_, index='0'):
diff --git a/js_tests/admin/RelatedObjectLookups.test.js b/js_tests/admin/RelatedObjectLookups.test.js
index 9ec1eed..04ad8bf 100644
--- a/js_tests/admin/RelatedObjectLookups.test.js
+++ b/js_tests/admin/RelatedObjectLookups.test.js
@@ -3,7 +3,11 @@
 /* eslint global-strict: 0, strict: 0 */
 'use strict';
 
-QUnit.module('admin.RelatedObjectLookups');
+QUnit.module('admin.RelatedObjectLookups', {
+    beforeEach: function() {
+        this.win = {name: 'id_teacher', close: function() {}};
+    }
+});
 
 QUnit.test('id_to_windowname', function(assert) {
     assert.equal(id_to_windowname('.test'), '__dot__test');
@@ -14,3 +18,122 @@ QUnit.test('windowname_to_id', function(assert) {
     assert.equal(windowname_to_id('__dot__test'), '.test');
     assert.equal(windowname_to_id('misc__dash__test'), 'misc-test');
 });
+
+QUnit.test('dismissAddRelatedObjectPopup/Select', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<select id="id_teacher" name="teacher"></select>').appendTo('div.related-widget-wrapper');
+    $('<option value="" selected="">---------</option>').appendTo('#id_teacher');
+
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').find('option').length, 2);
+    assert.equal($('#id_teacher').find('option').last().text(), 'Alex');
+    assert.ok($('#id_teacher').find('option').last()[0].selected);
+
+    dismissAddRelatedObjectPopup(this.win, '1', 'Susan');
+    assert.equal($('#id_teacher').find('option').length, 3);
+    assert.equal($('#id_teacher').find('option').last().text(), 'Susan');
+    // Only the last new item is marked as checked.
+    assert.equal($('#id_teacher').find('option:selected').length, 1);
+    assert.ok($('#id_teacher').find('option').last()[0].selected);
+});
+
+QUnit.test('dismissAddRelatedObjectPopup/SelectMultiple', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<select multiple="multiple" id="id_teacher" name="teacher"></select>').appendTo('div.related-widget-wrapper');
+
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').find('option').length, 1);
+    assert.equal($('#id_teacher').find('option').first().text(), 'Alex');
+    assert.ok($('#id_teacher').find('option').first()[0].selected);
+
+    dismissAddRelatedObjectPopup(this.win, '2', 'Susan');
+    assert.equal($('#id_teacher').find('option').length, 2);
+    assert.equal($('#id_teacher').find('option').last().text(), 'Susan');
+    // All new items are marked as checked.
+    assert.equal($('#id_teacher').find('option:selected').length, 2);
+    assert.ok($('#id_teacher').find('option').first()[0].selected);
+    assert.ok($('#id_teacher').find('option').last()[0].selected);
+});
+
+QUnit.test('dismissAddRelatedObjectPopup/TextInput', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<input id="id_teacher" name="teacher" type="text" value="">').appendTo('div.related-widget-wrapper');
+
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').val(), '1');
+
+    dismissAddRelatedObjectPopup(this.win, '2', 'Susan');
+    assert.equal($('#id_teacher').val(), '2');
+});
+
+QUnit.test('dismissAddRelatedObjectPopup/TextInput.vManyToManyRawIdAdminField', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<input id="id_teacher" name="teacher" type="text" value="" class="vManyToManyRawIdAdminField">').appendTo(
+        'div.related-widget-wrapper'
+    );
+
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').val(), '1');
+
+    dismissAddRelatedObjectPopup(this.win, '2', 'Susan');
+    assert.equal($('#id_teacher').val(), '1,2');
+});
+
+QUnit.test('dismissAddRelatedObjectPopup/RadioSelect', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<ul id="id_teacher" data-wrap-label="true" data-multiple="false"></ul>').appendTo('div.related-widget-wrapper');
+
+    // Add the first item.
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').find('li').length, 1);
+    assert.equal($('input#id_teacher_0').length, 1);
+    assert.equal($('input#id_teacher_0').val(), 1);
+    assert.equal($('#id_teacher').find('li').last().find('label').text(), ' Alex');
+    assert.equal($('#id_teacher').find('input').last()[0].type, "radio");
+    assert.ok($('#id_teacher').find('input').last()[0].checked);
+
+    // Add the other item.
+    dismissAddRelatedObjectPopup(this.win, '2', 'Susan');
+    assert.equal($('#id_teacher').find('li').length, 2);
+    assert.equal($('input#id_teacher_1').length, 1);
+    assert.equal($('input#id_teacher_1').val(), 2);
+    assert.equal($('#id_teacher').find('li').last().find('label').text(), ' Susan');
+    assert.equal($('#id_teacher').find('input').last()[0].type, "radio");
+    // Only the last new item is marked as checked like the select behavior.
+    assert.equal($('#id_teacher').find('input:checked').length, 1);
+    assert.notOk($('#id_teacher').find('input').first()[0].checked);
+    assert.ok($('#id_teacher').find('input').last()[0].checked);
+});
+
+QUnit.test('dismissAddRelatedObjectPopup/CheckboxSelectMultiple', function(assert) {
+    var $ = django.jQuery;
+    $('<div class="related-widget-wrapper"></div>').appendTo('#qunit-fixture');
+    $('<ul id="id_teacher" data-wrap-label="true" data-multiple="true"></ul>').appendTo('div.related-widget-wrapper');
+
+    // Add the first item.
+    dismissAddRelatedObjectPopup(this.win, '1', 'Alex');
+    assert.equal($('#id_teacher').find('li').length, 1);
+    assert.equal($('input#id_teacher_0').length, 1);
+    assert.equal($('input#id_teacher_0').val(), 1);
+    assert.equal($('#id_teacher').find('li').first().find('label').text(), ' Alex');
+    assert.equal($('#id_teacher').find('input').first()[0].type, "checkbox");
+    assert.ok($('#id_teacher').find('input').first()[0].checked);
+
+    // Add the other item.
+    dismissAddRelatedObjectPopup(this.win, '2', 'Susan');
+    assert.equal($('#id_teacher').find('li').length, 2);
+    assert.equal($('input#id_teacher_1').length, 1);
+    assert.equal($('input#id_teacher_1').val(), 2);
+    assert.equal($('#id_teacher').find('li').last().find('label').text(), ' Susan');
+    assert.equal($('#id_teacher').find('input').last()[0].type, "checkbox");
+    // All new items are marked as checked like the select multiple behavior.
+    assert.equal($('#id_teacher').find('input:checked').length, 2);
+    assert.ok($('#id_teacher').find('input').first()[0].checked);
+    assert.ok($('#id_teacher').find('input').last()[0].checked);
+});
+
diff --git a/tests/admin_widgets/models.py b/tests/admin_widgets/models.py
index 274c36e..9b3ed2b 100644
--- a/tests/admin_widgets/models.py
+++ b/tests/admin_widgets/models.py
@@ -163,3 +163,57 @@ class Profile(models.Model):
 
     def __str__(self):
         return self.user.username
+
+
+@python_2_unicode_compatible
+class Manager(models.Model):
+    name = models.CharField(max_length=255)
+
+    def __str__(self):
+        return self.name
+
+
+@python_2_unicode_compatible
+class Team(models.Model):
+    name = models.CharField(max_length=255)
+    team_manager = models.ForeignKey(Manager, models.CASCADE, null=True, blank=True)
+
+    def __str__(self):
+        return self.name
+
+
+@python_2_unicode_compatible
+class City(models.Model):
+    name = models.CharField(max_length=255)
+    teams = models.ManyToManyField(Team)
+
+    def __str__(self):
+        return self.name
+
+
+@python_2_unicode_compatible
+class Player(models.Model):
+    """
+    This model will be used to test ForeignKey widget relation field as
+    RadioSelect in RelatedFieldWidgetSeleniumTests, the default widget
+    will be overwritten in the test admin file.
+    """
+    name = models.CharField(max_length=255)
+    team = models.ForeignKey(Team, models.CASCADE, null=True, blank=True)
+
+    def __str__(self):
+        return self.name
+
+
+@python_2_unicode_compatible
+class Fan(models.Model):
+    """
+    This model will be used to test ManyToMany widget relation field as
+    CheckboxSelectMultiple in RelatedFieldWidgetSeleniumTests, the default
+    widget will be overwritten in the test admin file.
+    """
+    name = models.CharField(max_length=255)
+    teams = models.ManyToManyField(Team)
+
+    def __str__(self):
+        return self.name
diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py
index b74df4e..c54189f 100644
--- a/tests/admin_widgets/tests.py
+++ b/tests/admin_widgets/tests.py
@@ -23,8 +23,8 @@ from django.urls import reverse
 from django.utils import six, translation
 
 from .models import (
-    Advisor, Album, Band, Bee, Car, Company, Event, Honeycomb, Individual,
-    Inventory, Member, MyFileField, Profile, School, Student,
+    Advisor, Album, Band, Bee, Car, City, Company, Event, Fan, Honeycomb, Individual,
+    Inventory, Manager, Member, MyFileField, Player, Profile, School, Student, Team,
 )
 from .widgetadmin import site as widget_admin_site
 
@@ -1294,3 +1294,210 @@ class RelatedFieldWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
         profiles = Profile.objects.all()
         self.assertEqual(len(profiles), 1)
         self.assertEqual(profiles[0].user.username, username_value)
+
+    def test_ForeignKey_as_Select(self):
+        self.admin_login(username='super', password='secret', login_url='/')
+        self.selenium.get(self.live_server_url + reverse('admin:admin_widgets_team_add'))
+
+        main_window = self.selenium.current_window_handle
+        # Only an empty option in the Select
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team_manager option')), 1)
+
+        # Click the Add Manager button to add new
+        self.selenium.find_element_by_id('add_id_team_manager').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_team_manager')
+
+        manager_name_field = self.selenium.find_element_by_id('id_name')
+        manager_name_field.send_keys('Martin')
+
+        save_button_css_selector = '.submit-row > input[type=submit]'
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team_manager option')), 2)
+        new_manager = Manager.objects.get(pk=1)
+        self.assertEqual(new_manager.name, 'Martin')
+        new_option_selector = '#id_team_manager option[value="%d"]' % new_manager.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_option_selector).get_attribute('selected'))
+
+        # Click the Add Manager button to add other
+        self.selenium.find_element_by_id('add_id_team_manager').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_team_manager')
+
+        manager_name_field = self.selenium.find_element_by_id('id_name')
+        manager_name_field.send_keys('Joe')
+
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team_manager option')), 3)
+        new_manager = Manager.objects.get(pk=2)
+        self.assertEqual(new_manager.name, 'Joe')
+        new_option_selector = '#id_team_manager option[value="%d"]' % new_manager.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_option_selector).get_attribute('selected'))
+
+        # Go ahead and submit the form to make sure it works
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('Blue Jays')
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.wait_for_text('li.success', 'The team "Blue Jays" was added successfully.')
+        teams = Team.objects.all()
+        self.assertEqual(len(teams), 1)
+        # 'Joe' match because was the last selected Manager
+        self.assertEqual(teams[0].team_manager.name, 'Joe')
+
+    def test_ManyToMany_as_SelectMultiple(self):
+        self.admin_login(username='super', password='secret', login_url='/')
+        self.selenium.get(self.live_server_url + reverse('admin:admin_widgets_city_add'))
+
+        main_window = self.selenium.current_window_handle
+
+        # Click the Add Team button to add new
+        self.selenium.find_element_by_id('add_id_teams').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_teams')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('Cubs')
+
+        save_button_css_selector = '.submit-row > input[type=submit]'
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_teams option')), 1)
+        new_team = Team.objects.get(name='Cubs')
+        new_option_selector = '#id_teams option[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_option_selector).get_attribute('selected'))
+
+        # Click the Add Team button to add other
+        self.selenium.find_element_by_id('add_id_teams').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_teams')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('White Sox')
+
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_teams option')), 2)
+        new_team = Team.objects.get(name='White Sox')
+        new_option_selector = '#id_teams option[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_option_selector).get_attribute('selected'))
+
+        # Go ahead and submit the form to make sure it works
+        city_name_field = self.selenium.find_element_by_id('id_name')
+        city_name_field.send_keys('Chicago')
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.wait_for_text('li.success', 'The city "Chicago" was added successfully.')
+        cities = City.objects.all()
+        self.assertEqual(len(cities), 1)
+        self.assertEqual(cities[0].name, 'Chicago')
+        teams = cities[0].teams.all()
+        self.assertEqual(len(teams), 2)
+        self.assertListEqual([t.name for t in teams], ['Cubs', 'White Sox'])
+
+    def test_ForeignKey_as_RadioSelect(self):
+        self.admin_login(username='super', password='secret', login_url='/')
+        self.selenium.get(self.live_server_url + reverse('admin:admin_widgets_player_add'))
+
+        main_window = self.selenium.current_window_handle
+        # Only an empty option in the RadioSelect
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team li')), 1)
+
+        # Click the Add Team button to add new
+        self.selenium.find_element_by_id('add_id_team').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_team')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('Cardinals')
+
+        save_button_css_selector = '.submit-row > input[type=submit]'
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team li')), 2)
+        new_team = Team.objects.get(name='Cardinals')
+        new_input_selector = '#id_team li input[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_input_selector).get_attribute('checked'))
+
+        # Click the Add Team button to add other
+        self.selenium.find_element_by_id('add_id_team').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_team')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('Red Sox')
+
+        save_button_css_selector = '.submit-row > input[type=submit]'
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_team li')), 3)
+        new_team = Team.objects.get(name='Red Sox')
+        new_input_selector = '#id_team li input[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_input_selector).get_attribute('checked'))
+
+        # Go ahead and submit the form to make sure it works
+        player_name_field = self.selenium.find_element_by_id('id_name')
+        player_name_field.send_keys('David')
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.wait_for_text('li.success', 'The player "David" was added successfully.')
+        player = Player.objects.all()
+        self.assertEqual(len(player), 1)
+        # 'Red Sox' match because was the last selected Team
+        self.assertEqual(player[0].team.name, 'Red Sox')
+
+    def test_ManyToMany_as_CheckboxSelectMultiple(self):
+        self.admin_login(username='super', password='secret', login_url='/')
+        self.selenium.get(self.live_server_url + reverse('admin:admin_widgets_fan_add'))
+
+        main_window = self.selenium.current_window_handle
+
+        # Click the Add Team button to add new
+        self.selenium.find_element_by_id('add_id_teams').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_teams')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('Cubs')
+
+        save_button_css_selector = '.submit-row > input[type=submit]'
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_teams li')), 1)
+        new_team = Team.objects.get(name='Cubs')
+        new_input_selector = '#id_teams li input[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_input_selector).get_attribute('checked'))
+
+        # Click the Add Team button to add other
+        self.selenium.find_element_by_id('add_id_teams').click()
+        self.wait_for_popup()
+        self.selenium.switch_to.window('id_teams')
+
+        team_name_field = self.selenium.find_element_by_id('id_name')
+        team_name_field.send_keys('White Sox')
+
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.selenium.switch_to.window(main_window)
+
+        self.assertEqual(len(self.selenium.find_elements_by_css_selector('#id_teams li')), 2)
+        new_team = Team.objects.get(name='White Sox')
+        new_input_selector = '#id_teams li input[value="%d"]' % new_team.pk
+        self.assertTrue(self.selenium.find_element_by_css_selector(new_input_selector).get_attribute('checked'))
+
+        # Go ahead and submit the form to make sure it works
+        fan_name_field = self.selenium.find_element_by_id('id_name')
+        fan_name_field.send_keys('John')
+        self.selenium.find_element_by_css_selector(save_button_css_selector).click()
+        self.wait_for_text('li.success', 'The fan "John" was added successfully.')
+        fans = Fan.objects.all()
+        self.assertEqual(len(fans), 1)
+        self.assertEqual(fans[0].name, 'John')
+        teams = fans[0].teams.all()
+        self.assertEqual(len(teams), 2)
+        self.assertListEqual([t.name for t in teams], ['Cubs', 'White Sox'])
diff --git a/tests/admin_widgets/widgetadmin.py b/tests/admin_widgets/widgetadmin.py
index a03e044..235140f 100644
--- a/tests/admin_widgets/widgetadmin.py
+++ b/tests/admin_widgets/widgetadmin.py
@@ -1,8 +1,10 @@
+from django import forms
 from django.contrib import admin
+from django.forms import CheckboxSelectMultiple, RadioSelect
 
 from .models import (
-    Advisor, Album, Band, Bee, Car, CarTire, Event, Inventory, Member, Profile,
-    School, User,
+    Advisor, Album, Band, Bee, Car, CarTire, City, Event, Fan, Inventory,
+    Manager, Member, Player, Profile, School, Team, User,
 )
 
 
@@ -37,6 +39,30 @@ class SchoolAdmin(admin.ModelAdmin):
     filter_horizontal = ('alumni',)
 
 
+class PlayerForm(forms.ModelForm):
+
+    class Meta:
+        model = Player
+        fields = '__all__'
+        widgets = {'team': RadioSelect}
+
+
+class PlayerAdmin(admin.ModelAdmin):
+    form = PlayerForm
+
+
+class FanForm(forms.ModelForm):
+
+    class Meta:
+        model = Fan
+        fields = '__all__'
+        widgets = {'teams': CheckboxSelectMultiple}
+
+
+class FanAdmin(admin.ModelAdmin):
+    form = FanForm
+
+
 site = WidgetAdmin(name='widget-admin')
 
 site.register(User)
@@ -57,3 +83,9 @@ site.register(Advisor)
 site.register(School, SchoolAdmin)
 
 site.register(Profile)
+
+site.register(Team)
+site.register(Manager)
+site.register(City)
+site.register(Player, PlayerAdmin)
+site.register(Fan, FanAdmin)
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index 2b93575..bcfe74a 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -583,17 +583,17 @@ class FormsTestCase(SimpleTestCase):
             language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect)
 
         f = FrameworkForm(auto_id=False)
-        self.assertHTMLEqual(str(f['language']), """<ul>
+        self.assertHTMLEqual(str(f['language']), """<ul data-wrap-label="true" data-multiple="false">
 <li><label><input type="radio" name="language" value="P" required /> Python</label></li>
 <li><label><input type="radio" name="language" value="J" required /> Java</label></li>
 </ul>""")
         self.assertHTMLEqual(f.as_table(), """<tr><th>Name:</th><td><input type="text" name="name" required /></td></tr>
-<tr><th>Language:</th><td><ul>
+<tr><th>Language:</th><td><ul data-wrap-label="true" data-multiple="false">
 <li><label><input type="radio" name="language" value="P" required /> Python</label></li>
 <li><label><input type="radio" name="language" value="J" required /> Java</label></li>
 </ul></td></tr>""")
         self.assertHTMLEqual(f.as_ul(), """<li>Name: <input type="text" name="name" required /></li>
-<li>Language: <ul>
+<li>Language: <ul data-wrap-label="true" data-multiple="false">
 <li><label><input type="radio" name="language" value="P" required /> Python</label></li>
 <li><label><input type="radio" name="language" value="J" required /> Java</label></li>
 </ul></li>""")
@@ -604,7 +604,7 @@ class FormsTestCase(SimpleTestCase):
         f = FrameworkForm(auto_id='id_%s')
         self.assertHTMLEqual(
             str(f['language']),
-            """<ul id="id_language">
+            """<ul id="id_language" data-wrap-label="true" data-multiple="false">
 <li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
 Python</label></li>
 <li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
@@ -618,7 +618,7 @@ Java</label></li>
         self.assertHTMLEqual(
             f.as_table(),
             """<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" required /></td></tr>
-<tr><th><label for="id_language_0">Language:</label></th><td><ul id="id_language">
+<tr><th><label for="id_language_0">Language:</label></th><td><ul id="id_language" data-wrap-label="true" data-multiple="false">
 <li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
 Python</label></li>
 <li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
@@ -628,7 +628,7 @@ Java</label></li>
         self.assertHTMLEqual(
             f.as_ul(),
             """<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></li>
-<li><label for="id_language_0">Language:</label> <ul id="id_language">
+<li><label for="id_language_0">Language:</label> <ul id="id_language" data-wrap-label="true" data-multiple="false">
 <li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
 Python</label></li>
 <li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
@@ -638,7 +638,7 @@ Java</label></li>
         self.assertHTMLEqual(
             f.as_p(),
             """<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required /></p>
-<p><label for="id_language_0">Language:</label> <ul id="id_language">
+<p><label for="id_language_0">Language:</label> <ul id="id_language" data-wrap-label="true" data-multiple="false">
 <li><label for="id_language_0"><input type="radio" id="id_language_0" value="P" name="language" required />
 Python</label></li>
 <li><label for="id_language_1"><input type="radio" id="id_language_1" value="J" name="language" required />
@@ -851,17 +851,17 @@ Java</label></li>
             )
 
         f = SongForm(auto_id=False)
-        self.assertHTMLEqual(str(f['composers']), """<ul>
+        self.assertHTMLEqual(str(f['composers']), """<ul data-wrap-label="true" data-multiple="true">
 <li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li>
 <li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
 </ul>""")
         f = SongForm({'composers': ['J']}, auto_id=False)
-        self.assertHTMLEqual(str(f['composers']), """<ul>
+        self.assertHTMLEqual(str(f['composers']), """<ul data-wrap-label="true" data-multiple="true">
 <li><label><input checked type="checkbox" name="composers" value="J" /> John Lennon</label></li>
 <li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
 </ul>""")
         f = SongForm({'composers': ['J', 'P']}, auto_id=False)
-        self.assertHTMLEqual(str(f['composers']), """<ul>
+        self.assertHTMLEqual(str(f['composers']), """<ul data-wrap-label="true" data-multiple="true">
 <li><label><input checked type="checkbox" name="composers" value="J" /> John Lennon</label></li>
 <li><label><input checked type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
 </ul>""")
@@ -886,7 +886,7 @@ Java</label></li>
         f = SongForm(auto_id='%s_id')
         self.assertHTMLEqual(
             str(f['composers']),
-            """<ul id="composers_id">
+            """<ul id="composers_id" data-wrap-label="true" data-multiple="true">
 <li><label for="composers_id_0">
 <input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li>
 <li><label for="composers_id_1">
diff --git a/tests/forms_tests/tests/test_i18n.py b/tests/forms_tests/tests/test_i18n.py
index 56225e0..9f83295 100644
--- a/tests/forms_tests/tests/test_i18n.py
+++ b/tests/forms_tests/tests/test_i18n.py
@@ -59,7 +59,7 @@ class FormsI18nTests(SimpleTestCase):
         self.assertHTMLEqual(
             f.as_p(),
             '<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
-            '<ul id="id_somechoice">\n'
+            '<ul id="id_somechoice" data-wrap-label="true" data-multiple="false">\n'
             '<li><label for="id_somechoice_0">'
             '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
             'En tied\xe4</label></li>\n'
@@ -79,7 +79,8 @@ class FormsI18nTests(SimpleTestCase):
                 '\u041e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c'
                 '\u043d\u043e\u0435 \u043f\u043e\u043b\u0435.</li></ul>\n'
                 '<p><label for="id_somechoice_0">\xc5\xf8\xdf:</label>'
-                ' <ul id="id_somechoice">\n<li><label for="id_somechoice_0">'
+                ' <ul id="id_somechoice" data-wrap-label="true" data-multiple="false">\n'
+                '<li><label for="id_somechoice_0">'
                 '<input type="radio" id="id_somechoice_0" value="\xc5" name="somechoice" required /> '
                 'En tied\xe4</label></li>\n'
                 '<li><label for="id_somechoice_1">'
diff --git a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py
index a92e553..db42521 100644
--- a/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py
+++ b/tests/forms_tests/widget_tests/test_checkboxselectmultiple.py
@@ -9,7 +9,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
 
     def test_render_value(self):
         self.check_html(self.widget(choices=self.beatles), 'beatles', ['J'], html=(
-            """<ul>
+            """<ul data-wrap-label="true" data-multiple="true">
             <li><label><input checked type="checkbox" name="beatles" value="J" /> John</label></li>
             <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
             <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
@@ -19,7 +19,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
 
     def test_render_value_multiple(self):
         self.check_html(self.widget(choices=self.beatles), 'beatles', ['J', 'P'], html=(
-            """<ul>
+            """<ul data-wrap-label="true" data-multiple="true">
             <li><label><input checked type="checkbox" name="beatles" value="J" /> John</label></li>
             <li><label><input checked type="checkbox" name="beatles" value="P" /> Paul</label></li>
             <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
@@ -32,7 +32,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
         If the value is None, none of the options are selected.
         """
         self.check_html(self.widget(choices=self.beatles), 'beatles', None, html=(
-            """<ul>
+            """<ul data-wrap-label="true" data-multiple="true">
             <li><label><input type="checkbox" name="beatles" value="J" /> John</label></li>
             <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
             <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
@@ -47,7 +47,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
             ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))),
         )
         html = """
-        <ul id="media">
+        <ul id="media" data-wrap-label="true" data-multiple="true">
         <li>
         <label for="media_0"><input id="media_0" name="nestchoice" type="checkbox" value="unknown" /> Unknown</label>
         </li>
@@ -84,7 +84,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
         """
         choices = [('a', 'A'), ('b', 'B'), ('c', 'C')]
         html = """
-        <ul id="abc">
+        <ul id="abc" data-wrap-label="true" data-multiple="true">
         <li>
         <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
         </li>
@@ -102,7 +102,7 @@ class CheckboxSelectMultipleTest(WidgetTest):
         """
         widget = CheckboxSelectMultiple(attrs={'id': 'abc'}, choices=[('a', 'A'), ('b', 'B'), ('c', 'C')])
         html = """
-        <ul id="abc">
+        <ul id="abc" data-wrap-label="true" data-multiple="true">
         <li>
         <label for="abc_0"><input checked type="checkbox" name="letters" value="a" id="abc_0" /> A</label>
         </li>
diff --git a/tests/forms_tests/widget_tests/test_radioselect.py b/tests/forms_tests/widget_tests/test_radioselect.py
index fea26ce..df1cff5 100644
--- a/tests/forms_tests/widget_tests/test_radioselect.py
+++ b/tests/forms_tests/widget_tests/test_radioselect.py
@@ -8,7 +8,7 @@ class RadioSelectTest(WidgetTest):
 
     def test_render(self):
         self.check_html(self.widget(choices=self.beatles), 'beatle', 'J', html=(
-            """<ul>
+            """<ul data-wrap-label="true" data-multiple="false">
             <li><label><input checked type="radio" name="beatle" value="J" /> John</label></li>
             <li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
             <li><label><input type="radio" name="beatle" value="G" /> George</label></li>
@@ -23,7 +23,7 @@ class RadioSelectTest(WidgetTest):
             ('Video', (('vhs', 'VHS'), ('dvd', 'DVD'))),
         )
         html = """
-        <ul id="media">
+        <ul id="media" data-wrap-label="true" data-multiple="false">
         <li>
         <label for="media_0"><input id="media_0" name="nestchoice" type="radio" value="unknown" /> Unknown</label>
         </li>
@@ -55,7 +55,7 @@ class RadioSelectTest(WidgetTest):
         """
         widget = RadioSelect(attrs={'id': 'foo'}, choices=self.beatles)
         html = """
-        <ul id="foo">
+        <ul id="foo" data-wrap-label="true" data-multiple="false">
         <li>
         <label for="foo_0"><input checked type="radio" id="foo_0" value="J" name="beatle" /> John</label>
         </li>
@@ -72,7 +72,7 @@ class RadioSelectTest(WidgetTest):
         inputs.
         """
         html = """
-        <ul id="bar">
+        <ul id="bar" data-wrap-label="true" data-multiple="false">
         <li>
         <label for="bar_0"><input checked type="radio" id="bar_0" value="J" name="beatle" /> John</label>
         </li>
