mirror of
https://github.com/django/django.git
synced 2024-12-22 17:16:24 +00:00
Fixed #35870 -- Replaced blank select choice with accessible text.
Thanks James Scholes for providing feedback on accessible options, Thibaud Colas for running screen reader tests, Carlton Gibson for helping get started.
This commit is contained in:
parent
3ee4c6a27a
commit
b3505f38f6
@ -223,6 +223,9 @@ FORM_RENDERER = "django.forms.renderers.DjangoTemplates"
|
|||||||
# Set to True to assume "https" during the Django 5.x release cycle.
|
# Set to True to assume "https" during the Django 5.x release cycle.
|
||||||
FORMS_URLFIELD_ASSUME_HTTPS = False
|
FORMS_URLFIELD_ASSUME_HTTPS = False
|
||||||
|
|
||||||
|
# ToDo: Documentation string
|
||||||
|
FORMS_DEFAULT_BLANK_CHOICE_LABEL = gettext_noop("- Select an option -")
|
||||||
|
|
||||||
# Default email address to use for various automated correspondence from
|
# Default email address to use for various automated correspondence from
|
||||||
# the site managers.
|
# the site managers.
|
||||||
DEFAULT_FROM_EMAIL = "webmaster@localhost"
|
DEFAULT_FROM_EMAIL = "webmaster@localhost"
|
||||||
|
@ -1087,11 +1087,13 @@ class ModelAdmin(BaseModelAdmin):
|
|||||||
actions = self._filter_actions_by_permissions(request, self._get_base_actions())
|
actions = self._filter_actions_by_permissions(request, self._get_base_actions())
|
||||||
return {name: (func, name, desc) for func, name, desc in actions}
|
return {name: (func, name, desc) for func, name, desc in actions}
|
||||||
|
|
||||||
def get_action_choices(self, request, default_choices=models.BLANK_CHOICE_DASH):
|
def get_action_choices(self, request, default_choices=None):
|
||||||
"""
|
"""
|
||||||
Return a list of choices for use in a form object. Each choice is a
|
Return a list of choices for use in a form object. Each choice is a
|
||||||
tuple (name, description).
|
tuple (name, description).
|
||||||
"""
|
"""
|
||||||
|
if default_choices is None:
|
||||||
|
default_choices = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
choices = [] + default_choices
|
choices = [] + default_choices
|
||||||
for func, name, description in self.get_actions(request).values():
|
for func, name, description in self.get_actions(request).values():
|
||||||
choice = (name, description % model_format_dict(self.opts))
|
choice = (name, description % model_format_dict(self.opts))
|
||||||
|
@ -82,6 +82,7 @@ class NOT_PROVIDED:
|
|||||||
|
|
||||||
# The values to use for "blank" in SelectFields. Will be appended to the start
|
# The values to use for "blank" in SelectFields. Will be appended to the start
|
||||||
# of most "choices" lists.
|
# of most "choices" lists.
|
||||||
|
# ToDo: write deprecation notice per Trac issue #35870.
|
||||||
BLANK_CHOICE_DASH = [("", "---------")]
|
BLANK_CHOICE_DASH = [("", "---------")]
|
||||||
|
|
||||||
|
|
||||||
@ -1056,7 +1057,7 @@ class Field(RegisterLookupMixin):
|
|||||||
def get_choices(
|
def get_choices(
|
||||||
self,
|
self,
|
||||||
include_blank=True,
|
include_blank=True,
|
||||||
blank_choice=BLANK_CHOICE_DASH,
|
blank_choice=None,
|
||||||
limit_choices_to=None,
|
limit_choices_to=None,
|
||||||
ordering=(),
|
ordering=(),
|
||||||
):
|
):
|
||||||
@ -1064,6 +1065,8 @@ class Field(RegisterLookupMixin):
|
|||||||
Return choices with a default blank choices included, for use
|
Return choices with a default blank choices included, for use
|
||||||
as <select> choices for this field.
|
as <select> choices for this field.
|
||||||
"""
|
"""
|
||||||
|
if blank_choice is None:
|
||||||
|
blank_choice = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
if self.choices is not None:
|
if self.choices is not None:
|
||||||
if include_blank:
|
if include_blank:
|
||||||
return BlankChoiceIterator(self.choices, blank_choice)
|
return BlankChoiceIterator(self.choices, blank_choice)
|
||||||
|
@ -11,12 +11,12 @@ they're the closest concept currently available.
|
|||||||
|
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core import exceptions
|
from django.core import exceptions
|
||||||
from django.utils.deprecation import RemovedInDjango60Warning
|
from django.utils.deprecation import RemovedInDjango60Warning
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.hashable import make_hashable
|
from django.utils.hashable import make_hashable
|
||||||
|
|
||||||
from . import BLANK_CHOICE_DASH
|
|
||||||
from .mixins import FieldCacheMixin
|
from .mixins import FieldCacheMixin
|
||||||
|
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ class ForeignObjectRel(FieldCacheMixin):
|
|||||||
def get_choices(
|
def get_choices(
|
||||||
self,
|
self,
|
||||||
include_blank=True,
|
include_blank=True,
|
||||||
blank_choice=BLANK_CHOICE_DASH,
|
blank_choice=None,
|
||||||
limit_choices_to=None,
|
limit_choices_to=None,
|
||||||
ordering=(),
|
ordering=(),
|
||||||
):
|
):
|
||||||
@ -186,6 +186,8 @@ class ForeignObjectRel(FieldCacheMixin):
|
|||||||
Analog of django.db.models.fields.Field.get_choices(), provided
|
Analog of django.db.models.fields.Field.get_choices(), provided
|
||||||
initially for utilization by RelatedFieldListFilter.
|
initially for utilization by RelatedFieldListFilter.
|
||||||
"""
|
"""
|
||||||
|
if blank_choice is None:
|
||||||
|
blank_choice = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
limit_choices_to = limit_choices_to or self.limit_choices_to
|
limit_choices_to = limit_choices_to or self.limit_choices_to
|
||||||
qs = self.related_model._default_manager.complex_filter(limit_choices_to)
|
qs = self.related_model._default_manager.complex_filter(limit_choices_to)
|
||||||
if ordering:
|
if ordering:
|
||||||
|
@ -1217,7 +1217,7 @@ class FilePathField(ChoiceField):
|
|||||||
if self.required:
|
if self.required:
|
||||||
self.choices = []
|
self.choices = []
|
||||||
else:
|
else:
|
||||||
self.choices = [("", "---------")]
|
self.choices = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
|
|
||||||
if self.match is not None:
|
if self.match is not None:
|
||||||
self.match_re = re.compile(self.match)
|
self.match_re = re.compile(self.match)
|
||||||
|
@ -5,6 +5,7 @@ and database field objects.
|
|||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import (
|
from django.core.exceptions import (
|
||||||
NON_FIELD_ERRORS,
|
NON_FIELD_ERRORS,
|
||||||
FieldError,
|
FieldError,
|
||||||
@ -1456,7 +1457,7 @@ class ModelChoiceField(ChoiceField):
|
|||||||
self,
|
self,
|
||||||
queryset,
|
queryset,
|
||||||
*,
|
*,
|
||||||
empty_label="---------",
|
empty_label="",
|
||||||
required=True,
|
required=True,
|
||||||
widget=None,
|
widget=None,
|
||||||
label=None,
|
label=None,
|
||||||
@ -1483,6 +1484,8 @@ class ModelChoiceField(ChoiceField):
|
|||||||
):
|
):
|
||||||
self.empty_label = None
|
self.empty_label = None
|
||||||
else:
|
else:
|
||||||
|
if empty_label == "":
|
||||||
|
empty_label = settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL
|
||||||
self.empty_label = empty_label
|
self.empty_label = empty_label
|
||||||
self.queryset = queryset
|
self.queryset = queryset
|
||||||
self.limit_choices_to = limit_choices_to # limit the queryset later.
|
self.limit_choices_to = limit_choices_to # limit the queryset later.
|
||||||
|
@ -1376,7 +1376,7 @@ generating choices. See :ref:`iterating-relationship-choices` for details.
|
|||||||
|
|
||||||
By default the ``<select>`` widget used by ``ModelChoiceField`` will have an
|
By default the ``<select>`` widget used by ``ModelChoiceField`` will have an
|
||||||
empty choice at the top of the list. You can change the text of this
|
empty choice at the top of the list. You can change the text of this
|
||||||
label (which is ``"---------"`` by default) with the ``empty_label``
|
label (which is ``"- Select an option -"`` by default) with the ``empty_label``
|
||||||
attribute, or you can disable the empty label entirely by setting
|
attribute, or you can disable the empty label entirely by setting
|
||||||
``empty_label`` to ``None``::
|
``empty_label`` to ``None``::
|
||||||
|
|
||||||
|
@ -234,7 +234,7 @@ documentation.
|
|||||||
.. _field-choices-blank-label:
|
.. _field-choices-blank-label:
|
||||||
|
|
||||||
Unless :attr:`blank=False<Field.blank>` is set on the field along with a
|
Unless :attr:`blank=False<Field.blank>` is set on the field along with a
|
||||||
:attr:`~Field.default` then a label containing ``"---------"`` will be rendered
|
:attr:`~Field.default` then a label containing ``"- Select an option -"`` will be rendered
|
||||||
with the select box. To override this behavior, add a tuple to ``choices``
|
with the select box. To override this behavior, add a tuple to ``choices``
|
||||||
containing ``None``; e.g. ``(None, 'Your String For Display')``.
|
containing ``None``; e.g. ``(None, 'Your String For Display')``.
|
||||||
Alternatively, you can use an empty string instead of ``None`` where this makes
|
Alternatively, you can use an empty string instead of ``None`` where this makes
|
||||||
|
@ -1697,6 +1697,16 @@ Set this transitional setting to ``True`` to opt into using ``"https"`` as the
|
|||||||
new default value of :attr:`URLField.assume_scheme
|
new default value of :attr:`URLField.assume_scheme
|
||||||
<django.forms.URLField.assume_scheme>` during the Django 5.x release cycle.
|
<django.forms.URLField.assume_scheme>` during the Django 5.x release cycle.
|
||||||
|
|
||||||
|
.. setting:: FORMS_DEFAULT_BLANK_CHOICE_LABEL
|
||||||
|
|
||||||
|
``FORMS_DEFAULT_BLANK_CHOICE_LABEL``
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
Default: ``'- Select an option -'`` (Translated)
|
||||||
|
|
||||||
|
The default label for the blank choice option used by ``<select>`` elements in forms.
|
||||||
|
|
||||||
|
This value can be a regular or a translatable string, and can be overriden individually per form.
|
||||||
.. setting:: FORMAT_MODULE_PATH
|
.. setting:: FORMAT_MODULE_PATH
|
||||||
|
|
||||||
``FORMAT_MODULE_PATH``
|
``FORMAT_MODULE_PATH``
|
||||||
|
@ -294,7 +294,7 @@ class AdminActionsTest(TestCase):
|
|||||||
self.assertContains(
|
self.assertContains(
|
||||||
response,
|
response,
|
||||||
"""<label>Action: <select name="action" required>
|
"""<label>Action: <select name="action" required>
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="delete_selected">Delete selected external
|
<option value="delete_selected">Delete selected external
|
||||||
subscribers</option>
|
subscribers</option>
|
||||||
<option value="redirect_to">Redirect to (Awesome action)</option>
|
<option value="redirect_to">Redirect to (Awesome action)</option>
|
||||||
|
@ -110,7 +110,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
fk_dropdown.get_attribute("innerHTML"),
|
fk_dropdown.get_attribute("innerHTML"),
|
||||||
f"""
|
f"""
|
||||||
<option value="" selected="">---------</option>
|
<option value="" selected="">- Select an option -</option>
|
||||||
<option value="{id_value}" selected>{interesting_name}</option>
|
<option value="{id_value}" selected>{interesting_name}</option>
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
@ -155,7 +155,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
fk_dropdown.get_attribute("innerHTML"),
|
fk_dropdown.get_attribute("innerHTML"),
|
||||||
f"""
|
f"""
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="{id_value}">{name}</option>
|
<option value="{id_value}">{name}</option>
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ from unittest import mock
|
|||||||
from urllib.parse import parse_qsl, urljoin, urlsplit
|
from urllib.parse import parse_qsl, urljoin, urlsplit
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.contrib.admin import AdminSite, ModelAdmin
|
from django.contrib.admin import AdminSite, ModelAdmin
|
||||||
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
|
from django.contrib.admin.helpers import ACTION_CHECKBOX_NAME
|
||||||
@ -6450,7 +6451,9 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.selenium.switch_to.window(self.selenium.window_handles[0])
|
self.selenium.switch_to.window(self.selenium.window_handles[0])
|
||||||
select = Select(self.selenium.find_element(By.ID, "id_parent"))
|
select = Select(self.selenium.find_element(By.ID, "id_parent"))
|
||||||
self.assertEqual(ParentWithUUIDPK.objects.count(), 0)
|
self.assertEqual(ParentWithUUIDPK.objects.count(), 0)
|
||||||
self.assertEqual(select.first_selected_option.text, "---------")
|
self.assertEqual(
|
||||||
|
select.first_selected_option.text, settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL
|
||||||
|
)
|
||||||
self.assertEqual(select.first_selected_option.get_attribute("value"), "")
|
self.assertEqual(select.first_selected_option.get_attribute("value"), "")
|
||||||
|
|
||||||
def test_inline_with_popup_cancel_delete(self):
|
def test_inline_with_popup_cancel_delete(self):
|
||||||
@ -6696,7 +6699,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(born_country_select_id),
|
_get_HTML_inside_element_by_id(born_country_select_id),
|
||||||
"""
|
"""
|
||||||
<option value="" selected="">---------</option>
|
<option value="" selected="">- Select an option -</option>
|
||||||
<option value="1" selected="">Argentina</option>
|
<option value="1" selected="">Argentina</option>
|
||||||
""",
|
""",
|
||||||
)
|
)
|
||||||
@ -6715,7 +6718,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
# limit_choices_to.
|
# limit_choices_to.
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
||||||
'<option value="" selected="">---------</option>',
|
'<option value="" selected="">- Select an option -</option>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add new Country from the living_country select.
|
# Add new Country from the living_country select.
|
||||||
@ -6734,7 +6737,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(born_country_select_id),
|
_get_HTML_inside_element_by_id(born_country_select_id),
|
||||||
"""
|
"""
|
||||||
<option value="" selected="">---------</option>
|
<option value="" selected="">- Select an option -</option>
|
||||||
<option value="1" selected="">Argentina</option>
|
<option value="1" selected="">Argentina</option>
|
||||||
<option value="2">Spain</option>
|
<option value="2">Spain</option>
|
||||||
""",
|
""",
|
||||||
@ -6756,7 +6759,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
# limit_choices_to.
|
# limit_choices_to.
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
||||||
'<option value="" selected="">---------</option>',
|
'<option value="" selected="">- Select an option -</option>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Edit second Country created from living_country select.
|
# Edit second Country created from living_country select.
|
||||||
@ -6776,7 +6779,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(born_country_select_id),
|
_get_HTML_inside_element_by_id(born_country_select_id),
|
||||||
"""
|
"""
|
||||||
<option value="" selected="">---------</option>
|
<option value="" selected="">- Select an option -</option>
|
||||||
<option value="1" selected="">Argentina</option>
|
<option value="1" selected="">Argentina</option>
|
||||||
<option value="2">Italy</option>
|
<option value="2">Italy</option>
|
||||||
""",
|
""",
|
||||||
@ -6796,7 +6799,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
|||||||
# favorite_country_to_vacation field has no options.
|
# favorite_country_to_vacation field has no options.
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
_get_HTML_inside_element_by_id(favorite_country_to_vacation_select_id),
|
||||||
'<option value="" selected="">---------</option>',
|
'<option value="" selected="">- Select an option -</option>',
|
||||||
)
|
)
|
||||||
|
|
||||||
# Add a new Asian country.
|
# Add a new Asian country.
|
||||||
|
@ -1811,7 +1811,7 @@ class RelatedFieldWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
|
|||||||
|
|
||||||
# Chrome and Safari don't update related object links when selecting
|
# Chrome and Safari don't update related object links when selecting
|
||||||
# the same option as previously submitted. As a consequence, the
|
# the same option as previously submitted. As a consequence, the
|
||||||
# "pencil" and "eye" buttons remain disable, so select "---------"
|
# "pencil" and "eye" buttons remain disable, so select "- Select an option -"
|
||||||
# first.
|
# first.
|
||||||
select = Select(self.selenium.find_element(By.ID, "id_user"))
|
select = Select(self.selenium.find_element(By.ID, "id_user"))
|
||||||
select.select_by_index(0)
|
select.select_by_index(0)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import decimal
|
import decimal
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms import TypedChoiceField
|
from django.forms import TypedChoiceField
|
||||||
from django.test import SimpleTestCase
|
from django.test import SimpleTestCase
|
||||||
@ -59,7 +60,11 @@ class TypedChoiceFieldTest(SimpleTestCase):
|
|||||||
self.assertFalse(f.has_changed("1", "1"))
|
self.assertFalse(f.has_changed("1", "1"))
|
||||||
|
|
||||||
f = TypedChoiceField(
|
f = TypedChoiceField(
|
||||||
choices=[("", "---------"), ("a", "a"), ("b", "b")],
|
choices=[
|
||||||
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
|
("a", "a"),
|
||||||
|
("b", "b"),
|
||||||
|
],
|
||||||
coerce=str,
|
coerce=str,
|
||||||
required=False,
|
required=False,
|
||||||
initial=None,
|
initial=None,
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.forms import ChoiceField, Form, MultiWidget, RadioSelect, TextInput
|
from django.forms import ChoiceField, Form, MultiWidget, RadioSelect, TextInput
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
from .test_choicewidget import ChoiceWidgetTest
|
from .test_choicewidget import ChoiceWidgetTest
|
||||||
|
|
||||||
BLANK_CHOICE_DASH = (("", "------"),)
|
BLANK_CHOICE = (("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),)
|
||||||
|
|
||||||
|
|
||||||
class RadioSelectTest(ChoiceWidgetTest):
|
class RadioSelectTest(ChoiceWidgetTest):
|
||||||
@ -16,7 +17,9 @@ class RadioSelectTest(ChoiceWidgetTest):
|
|||||||
html = """
|
html = """
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<label><input type="radio" name="beatle" value="">------</label>
|
<label>
|
||||||
|
<input type="radio" name="beatle" value="">- Select an option -
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label><input checked type="radio" name="beatle" value="J">John</label>
|
<label><input checked type="radio" name="beatle" value="J">John</label>
|
||||||
@ -32,7 +35,7 @@ class RadioSelectTest(ChoiceWidgetTest):
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
"""
|
"""
|
||||||
beatles_with_blank = BLANK_CHOICE_DASH + self.beatles
|
beatles_with_blank = BLANK_CHOICE + self.beatles
|
||||||
for choices in (beatles_with_blank, dict(beatles_with_blank)):
|
for choices in (beatles_with_blank, dict(beatles_with_blank)):
|
||||||
with self.subTest(choices):
|
with self.subTest(choices):
|
||||||
self.check_html(self.widget(choices=choices), "beatle", "J", html=html)
|
self.check_html(self.widget(choices=choices), "beatle", "J", html=html)
|
||||||
@ -83,11 +86,13 @@ class RadioSelectTest(ChoiceWidgetTest):
|
|||||||
"""
|
"""
|
||||||
If value is None, none of the options are selected.
|
If value is None, none of the options are selected.
|
||||||
"""
|
"""
|
||||||
choices = BLANK_CHOICE_DASH + self.beatles
|
choices = BLANK_CHOICE + self.beatles
|
||||||
html = """
|
html = """
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<label><input checked type="radio" name="beatle" value="">------</label>
|
<label>
|
||||||
|
<input checked type="radio" name="beatle" value="">- Select an option -
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label><input type="radio" name="beatle" value="J">John</label>
|
<label><input type="radio" name="beatle" value="J">John</label>
|
||||||
@ -463,11 +468,11 @@ class RadioSelectTest(ChoiceWidgetTest):
|
|||||||
|
|
||||||
def test_render_as_subwidget(self):
|
def test_render_as_subwidget(self):
|
||||||
"""A RadioSelect as a subwidget of MultiWidget."""
|
"""A RadioSelect as a subwidget of MultiWidget."""
|
||||||
choices = BLANK_CHOICE_DASH + self.beatles
|
choices = BLANK_CHOICE + self.beatles
|
||||||
html = """
|
html = """
|
||||||
<div>
|
<div>
|
||||||
<div><label>
|
<div><label>
|
||||||
<input type="radio" name="beatle_0" value="">------</label>
|
<input type="radio" name="beatle_0" value="">- Select an option -</label>
|
||||||
</div>
|
</div>
|
||||||
<div><label>
|
<div><label>
|
||||||
<input checked type="radio" name="beatle_0" value="J">John</label>
|
<input checked type="radio" name="beatle_0" value="J">John</label>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import IntegrityError, models, transaction
|
from django.db import IntegrityError, models, transaction
|
||||||
from django.test import SimpleTestCase, TestCase
|
from django.test import SimpleTestCase, TestCase
|
||||||
@ -48,7 +49,10 @@ class BooleanFieldTests(TestCase):
|
|||||||
"""
|
"""
|
||||||
choices = [(1, "Si"), (2, "No")]
|
choices = [(1, "Si"), (2, "No")]
|
||||||
f = models.BooleanField(choices=choices)
|
f = models.BooleanField(choices=choices)
|
||||||
self.assertEqual(f.formfield().choices, [("", "---------")] + choices)
|
self.assertEqual(
|
||||||
|
f.formfield().choices,
|
||||||
|
[("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)] + choices,
|
||||||
|
)
|
||||||
|
|
||||||
def test_nullbooleanfield_formfield(self):
|
def test_nullbooleanfield_formfield(self):
|
||||||
f = models.BooleanField(null=True)
|
f = models.BooleanField(null=True)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import pickle
|
import pickle
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import SimpleTestCase, TestCase
|
from django.test import SimpleTestCase, TestCase
|
||||||
@ -354,7 +355,10 @@ class GetChoicesTests(SimpleTestCase):
|
|||||||
def test_lazy_strings_not_evaluated(self):
|
def test_lazy_strings_not_evaluated(self):
|
||||||
lazy_func = lazy(lambda x: 0 / 0, int) # raises ZeroDivisionError if evaluated.
|
lazy_func = lazy(lambda x: 0 / 0, int) # raises ZeroDivisionError if evaluated.
|
||||||
f = models.CharField(choices=[(lazy_func("group"), [("a", "A"), ("b", "B")])])
|
f = models.CharField(choices=[(lazy_func("group"), [("a", "A"), ("b", "B")])])
|
||||||
self.assertEqual(f.get_choices(include_blank=True)[0], ("", "---------"))
|
self.assertEqual(
|
||||||
|
f.get_choices(include_blank=True)[0],
|
||||||
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class GetChoicesOrderingTests(TestCase):
|
class GetChoicesOrderingTests(TestCase):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.forms.models import ModelChoiceIterator, ModelChoiceIteratorValue
|
from django.forms.models import ModelChoiceIterator, ModelChoiceIteratorValue
|
||||||
from django.forms.widgets import CheckboxSelectMultiple
|
from django.forms.widgets import CheckboxSelectMultiple
|
||||||
@ -24,7 +25,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
(self.c3.pk, "Third"),
|
(self.c3.pk, "Third"),
|
||||||
@ -102,7 +103,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
],
|
],
|
||||||
@ -118,7 +119,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(gen_two),
|
list(gen_two),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
],
|
],
|
||||||
@ -130,7 +131,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "category Entertainment"),
|
(self.c1.pk, "category Entertainment"),
|
||||||
(self.c2.pk, "category A test"),
|
(self.c2.pk, "category A test"),
|
||||||
(self.c3.pk, "category Third"),
|
(self.c3.pk, "category Third"),
|
||||||
@ -143,7 +144,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
(self.c3.pk, "Third"),
|
(self.c3.pk, "Third"),
|
||||||
@ -154,7 +155,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
(self.c3.pk, "Third"),
|
(self.c3.pk, "Third"),
|
||||||
@ -174,6 +175,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertIs(bool(f.choices), True)
|
self.assertIs(bool(f.choices), True)
|
||||||
|
|
||||||
def test_choices_radio_blank(self):
|
def test_choices_radio_blank(self):
|
||||||
|
blank_choice = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
choices = [
|
choices = [
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
@ -190,7 +192,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[("", "---------")] + choices if blank else choices,
|
(blank_choice + choices if blank else choices),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_deepcopies_widget(self):
|
def test_deepcopies_widget(self):
|
||||||
@ -425,7 +427,7 @@ class ModelChoiceFieldTests(TestCase):
|
|||||||
self.assertCountEqual(
|
self.assertCountEqual(
|
||||||
list(f.choices),
|
list(f.choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(self.c1.pk, "Entertainment"),
|
(self.c1.pk, "Entertainment"),
|
||||||
(self.c2.pk, "A test"),
|
(self.c2.pk, "A test"),
|
||||||
(self.c3.pk, "Third"),
|
(self.c3.pk, "Third"),
|
||||||
|
@ -5,6 +5,7 @@ from decimal import Decimal
|
|||||||
from unittest import mock, skipUnless
|
from unittest import mock, skipUnless
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.core.exceptions import (
|
from django.core.exceptions import (
|
||||||
NON_FIELD_ERRORS,
|
NON_FIELD_ERRORS,
|
||||||
FieldError,
|
FieldError,
|
||||||
@ -341,7 +342,7 @@ class ModelFormBaseTest(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(form.fields["author"].choices),
|
list(form.fields["author"].choices),
|
||||||
[
|
[
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(writer.pk, "Joe Doe"),
|
(writer.pk, "Joe Doe"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -1534,7 +1535,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<li>Slug: <input type="text" name="slug" maxlength="50" required></li>
|
<li>Slug: <input type="text" name="slug" maxlength="50" required></li>
|
||||||
<li>Pub date: <input type="text" name="pub_date" required></li>
|
<li>Pub date: <input type="text" name="pub_date" required></li>
|
||||||
<li>Writer: <select name="writer" required>
|
<li>Writer: <select name="writer" required>
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="%s">Bob Woodward</option>
|
<option value="%s">Bob Woodward</option>
|
||||||
<option value="%s">Mike Royko</option>
|
<option value="%s">Mike Royko</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
@ -1546,7 +1547,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<option value="%s">Third test</option>
|
<option value="%s">Third test</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
<li>Status: <select name="status">
|
<li>Status: <select name="status">
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="1">Draft</option>
|
<option value="1">Draft</option>
|
||||||
<option value="2">Pending</option>
|
<option value="2">Pending</option>
|
||||||
<option value="3">Live</option>
|
<option value="3">Live</option>
|
||||||
@ -1588,7 +1589,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<li>Pub date:
|
<li>Pub date:
|
||||||
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
||||||
<li>Writer: <select name="writer" required>
|
<li>Writer: <select name="writer" required>
|
||||||
<option value="">---------</option>
|
<option value="">- Select an option -</option>
|
||||||
<option value="%s">Bob Woodward</option>
|
<option value="%s">Bob Woodward</option>
|
||||||
<option value="%s" selected>Mike Royko</option>
|
<option value="%s" selected>Mike Royko</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
@ -1600,7 +1601,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<option value="%s">Third test</option>
|
<option value="%s">Third test</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
<li>Status: <select name="status">
|
<li>Status: <select name="status">
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="1">Draft</option>
|
<option value="1">Draft</option>
|
||||||
<option value="2">Pending</option>
|
<option value="2">Pending</option>
|
||||||
<option value="3">Live</option>
|
<option value="3">Live</option>
|
||||||
@ -1733,7 +1734,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
</div>
|
</div>
|
||||||
<div>Writer:
|
<div>Writer:
|
||||||
<select name="writer" required>
|
<select name="writer" required>
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="%s">Bob Woodward</option>
|
<option value="%s">Bob Woodward</option>
|
||||||
<option value="%s">Mike Royko</option>
|
<option value="%s">Mike Royko</option>
|
||||||
</select>
|
</select>
|
||||||
@ -1750,7 +1751,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
</div>
|
</div>
|
||||||
<div>Status:
|
<div>Status:
|
||||||
<select name="status">
|
<select name="status">
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="1">Draft</option><option value="2">Pending</option>
|
<option value="1">Draft</option><option value="2">Pending</option>
|
||||||
<option value="3">Live</option>
|
<option value="3">Live</option>
|
||||||
</select>
|
</select>
|
||||||
@ -1783,7 +1784,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<li>Pub date:
|
<li>Pub date:
|
||||||
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
||||||
<li>Writer: <select name="writer" required>
|
<li>Writer: <select name="writer" required>
|
||||||
<option value="">---------</option>
|
<option value="">- Select an option -</option>
|
||||||
<option value="%s">Bob Woodward</option>
|
<option value="%s">Bob Woodward</option>
|
||||||
<option value="%s" selected>Mike Royko</option>
|
<option value="%s" selected>Mike Royko</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
@ -1795,7 +1796,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
<option value="%s">Third test</option>
|
<option value="%s">Third test</option>
|
||||||
</select></li>
|
</select></li>
|
||||||
<li>Status: <select name="status">
|
<li>Status: <select name="status">
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="1">Draft</option>
|
<option value="1">Draft</option>
|
||||||
<option value="2">Pending</option>
|
<option value="2">Pending</option>
|
||||||
<option value="3">Live</option>
|
<option value="3">Live</option>
|
||||||
@ -1957,7 +1958,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
||||||
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
||||||
'<li>Writer: <select name="writer" required>'
|
'<li>Writer: <select name="writer" required>'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="%s">Bob Woodward</option>'
|
'<option value="%s">Bob Woodward</option>'
|
||||||
'<option value="%s">Mike Royko</option>'
|
'<option value="%s">Mike Royko</option>'
|
||||||
"</select></li>"
|
"</select></li>"
|
||||||
@ -1969,7 +1970,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
'<option value="%s">Third test</option>'
|
'<option value="%s">Third test</option>'
|
||||||
"</select> </li>"
|
"</select> </li>"
|
||||||
'<li>Status: <select name="status">'
|
'<li>Status: <select name="status">'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="1">Draft</option>'
|
'<option value="1">Draft</option>'
|
||||||
'<option value="2">Pending</option>'
|
'<option value="2">Pending</option>'
|
||||||
'<option value="3">Live</option>'
|
'<option value="3">Live</option>'
|
||||||
@ -1986,7 +1987,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
||||||
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
||||||
'<li>Writer: <select name="writer" required>'
|
'<li>Writer: <select name="writer" required>'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="%s">Bob Woodward</option>'
|
'<option value="%s">Bob Woodward</option>'
|
||||||
'<option value="%s">Carl Bernstein</option>'
|
'<option value="%s">Carl Bernstein</option>'
|
||||||
'<option value="%s">Mike Royko</option>'
|
'<option value="%s">Mike Royko</option>'
|
||||||
@ -2000,7 +2001,7 @@ class ModelFormBasicTests(TestCase):
|
|||||||
'<option value="%s">Fourth</option>'
|
'<option value="%s">Fourth</option>'
|
||||||
"</select></li>"
|
"</select></li>"
|
||||||
'<li>Status: <select name="status">'
|
'<li>Status: <select name="status">'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="1">Draft</option>'
|
'<option value="1">Draft</option>'
|
||||||
'<option value="2">Pending</option>'
|
'<option value="2">Pending</option>'
|
||||||
'<option value="3">Live</option>'
|
'<option value="3">Live</option>'
|
||||||
@ -2044,7 +2045,8 @@ class ModelFormBasicTests(TestCase):
|
|||||||
self.assertEqual(call_count, 0)
|
self.assertEqual(call_count, 0)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
form.fields["animal"].choices,
|
form.fields["animal"].choices,
|
||||||
models.BLANK_CHOICE_DASH + [("LION", "Lion"), ("ZEBRA", "Zebra")],
|
[("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||||
|
+ [("LION", "Lion"), ("ZEBRA", "Zebra")],
|
||||||
)
|
)
|
||||||
self.assertEqual(call_count, 1)
|
self.assertEqual(call_count, 1)
|
||||||
|
|
||||||
@ -2410,7 +2412,7 @@ class ModelOneToOneFieldTests(TestCase):
|
|||||||
"""
|
"""
|
||||||
<p><label for="id_writer">Writer:</label>
|
<p><label for="id_writer">Writer:</label>
|
||||||
<select name="writer" id="id_writer" required>
|
<select name="writer" id="id_writer" required>
|
||||||
<option value="" selected>---------</option>
|
<option value="" selected>- Select an option -</option>
|
||||||
<option value="%s">Bob Woodward</option>
|
<option value="%s">Bob Woodward</option>
|
||||||
<option value="%s">Mike Royko</option>
|
<option value="%s">Mike Royko</option>
|
||||||
</select></p>
|
</select></p>
|
||||||
@ -2437,7 +2439,7 @@ class ModelOneToOneFieldTests(TestCase):
|
|||||||
"""
|
"""
|
||||||
<p><label for="id_writer">Writer:</label>
|
<p><label for="id_writer">Writer:</label>
|
||||||
<select name="writer" id="id_writer" required>
|
<select name="writer" id="id_writer" required>
|
||||||
<option value="">---------</option>
|
<option value="">- Select an option -</option>
|
||||||
<option value="%s" selected>Bob Woodward</option>
|
<option value="%s" selected>Bob Woodward</option>
|
||||||
<option value="%s">Mike Royko</option>
|
<option value="%s">Mike Royko</option>
|
||||||
</select></p>
|
</select></p>
|
||||||
@ -2726,7 +2728,8 @@ class FileAndImageFieldTests(TestCase):
|
|||||||
|
|
||||||
form = FPForm()
|
form = FPForm()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
[name for _, name in form["path"].field.choices], ["---------", "models.py"]
|
[name for _, name in form["path"].field.choices],
|
||||||
|
[settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL, "models.py"],
|
||||||
)
|
)
|
||||||
|
|
||||||
@skipUnless(test_images, "Pillow not installed")
|
@skipUnless(test_images, "Pillow not installed")
|
||||||
@ -3055,7 +3058,7 @@ class OtherModelFormTests(TestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
tuple(field.choices),
|
tuple(field.choices),
|
||||||
(
|
(
|
||||||
("", "---------"),
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
(multicolor_item.pk, "blue, red"),
|
(multicolor_item.pk, "blue, red"),
|
||||||
(red_item.pk, "red"),
|
(red_item.pk, "red"),
|
||||||
),
|
),
|
||||||
@ -3069,14 +3072,19 @@ class OtherModelFormTests(TestCase):
|
|||||||
field = forms.ModelChoiceField(Inventory.objects.all(), to_field_name="barcode")
|
field = forms.ModelChoiceField(Inventory.objects.all(), to_field_name="barcode")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
tuple(field.choices),
|
tuple(field.choices),
|
||||||
(("", "---------"), (86, "Apple"), (87, "Core"), (22, "Pear")),
|
(
|
||||||
|
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||||
|
(86, "Apple"),
|
||||||
|
(87, "Core"),
|
||||||
|
(22, "Pear"),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
form = InventoryForm(instance=core)
|
form = InventoryForm(instance=core)
|
||||||
self.assertHTMLEqual(
|
self.assertHTMLEqual(
|
||||||
str(form["parent"]),
|
str(form["parent"]),
|
||||||
"""<select name="parent" id="id_parent">
|
"""<select name="parent" id="id_parent">
|
||||||
<option value="">---------</option>
|
<option value="">- Select an option -</option>
|
||||||
<option value="86" selected>Apple</option>
|
<option value="86" selected>Apple</option>
|
||||||
<option value="87">Core</option>
|
<option value="87">Core</option>
|
||||||
<option value="22">Pear</option>
|
<option value="22">Pear</option>
|
||||||
|
@ -1267,7 +1267,7 @@ class ModelFormsetTest(TestCase):
|
|||||||
formset.forms[0].as_p(),
|
formset.forms[0].as_p(),
|
||||||
'<p><label for="id_form-0-owner">Owner:</label>'
|
'<p><label for="id_form-0-owner">Owner:</label>'
|
||||||
'<select name="form-0-owner" id="id_form-0-owner">'
|
'<select name="form-0-owner" id="id_form-0-owner">'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="%d">Joe Perry at Giordanos</option>'
|
'<option value="%d">Joe Perry at Giordanos</option>'
|
||||||
'<option value="%d">Jack Berry at Giordanos</option>'
|
'<option value="%d">Jack Berry at Giordanos</option>'
|
||||||
"</select></p>"
|
"</select></p>"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from datetime import date
|
from datetime import date
|
||||||
|
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry
|
from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry
|
||||||
from django.contrib.admin.options import (
|
from django.contrib.admin.options import (
|
||||||
HORIZONTAL,
|
HORIZONTAL,
|
||||||
@ -664,7 +665,7 @@ class ModelAdminTests(TestCase):
|
|||||||
'<div class="related-widget-wrapper" data-model-ref="band">'
|
'<div class="related-widget-wrapper" data-model-ref="band">'
|
||||||
'<select data-context="available-source" '
|
'<select data-context="available-source" '
|
||||||
'name="main_band" id="id_main_band" required>'
|
'name="main_band" id="id_main_band" required>'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="%d">The Beatles</option>'
|
'<option value="%d">The Beatles</option>'
|
||||||
'<option value="%d">The Doors</option>'
|
'<option value="%d">The Doors</option>'
|
||||||
"</select></div>" % (band2.id, self.band.id),
|
"</select></div>" % (band2.id, self.band.id),
|
||||||
@ -688,7 +689,7 @@ class ModelAdminTests(TestCase):
|
|||||||
'<div class="related-widget-wrapper" data-model-ref="band">'
|
'<div class="related-widget-wrapper" data-model-ref="band">'
|
||||||
'<select data-context="available-source" '
|
'<select data-context="available-source" '
|
||||||
'name="main_band" id="id_main_band" required>'
|
'name="main_band" id="id_main_band" required>'
|
||||||
'<option value="" selected>---------</option>'
|
'<option value="" selected>- Select an option -</option>'
|
||||||
'<option value="%d">The Doors</option>'
|
'<option value="%d">The Doors</option>'
|
||||||
"</select></div>" % self.band.id,
|
"</select></div>" % self.band.id,
|
||||||
)
|
)
|
||||||
@ -736,29 +737,30 @@ class ModelAdminTests(TestCase):
|
|||||||
# ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so
|
# ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so
|
||||||
# they need to be handled properly when type checking. For Select fields, all of
|
# they need to be handled properly when type checking. For Select fields, all of
|
||||||
# the choices lists have a first entry of dashes.
|
# the choices lists have a first entry of dashes.
|
||||||
|
blank_option = ("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)
|
||||||
cma = ModelAdmin(Concert, self.site)
|
cma = ModelAdmin(Concert, self.site)
|
||||||
cmafa = cma.get_form(request)
|
cmafa = cma.get_form(request)
|
||||||
|
|
||||||
self.assertEqual(type(cmafa.base_fields["main_band"].widget.widget), Select)
|
self.assertEqual(type(cmafa.base_fields["main_band"].widget.widget), Select)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(cmafa.base_fields["main_band"].widget.choices),
|
list(cmafa.base_fields["main_band"].widget.choices),
|
||||||
[("", "---------"), (self.band.id, "The Doors")],
|
[blank_option, (self.band.id, "The Doors")],
|
||||||
)
|
)
|
||||||
|
|
||||||
self.assertEqual(type(cmafa.base_fields["opening_band"].widget.widget), Select)
|
self.assertEqual(type(cmafa.base_fields["opening_band"].widget.widget), Select)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(cmafa.base_fields["opening_band"].widget.choices),
|
list(cmafa.base_fields["opening_band"].widget.choices),
|
||||||
[("", "---------"), (self.band.id, "The Doors")],
|
[blank_option, (self.band.id, "The Doors")],
|
||||||
)
|
)
|
||||||
self.assertEqual(type(cmafa.base_fields["day"].widget), Select)
|
self.assertEqual(type(cmafa.base_fields["day"].widget), Select)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(cmafa.base_fields["day"].widget.choices),
|
list(cmafa.base_fields["day"].widget.choices),
|
||||||
[("", "---------"), (1, "Fri"), (2, "Sat")],
|
[blank_option, (1, "Fri"), (2, "Sat")],
|
||||||
)
|
)
|
||||||
self.assertEqual(type(cmafa.base_fields["transport"].widget), Select)
|
self.assertEqual(type(cmafa.base_fields["transport"].widget), Select)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(cmafa.base_fields["transport"].widget.choices),
|
list(cmafa.base_fields["transport"].widget.choices),
|
||||||
[("", "---------"), (1, "Plane"), (2, "Train"), (3, "Bus")],
|
[blank_option, (1, "Plane"), (2, "Train"), (3, "Bus")],
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_foreign_key_as_radio_field(self):
|
def test_foreign_key_as_radio_field(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user