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.
|
||||
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
|
||||
# the site managers.
|
||||
DEFAULT_FROM_EMAIL = "webmaster@localhost"
|
||||
|
@ -1087,11 +1087,13 @@ class ModelAdmin(BaseModelAdmin):
|
||||
actions = self._filter_actions_by_permissions(request, self._get_base_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
|
||||
tuple (name, description).
|
||||
"""
|
||||
if default_choices is None:
|
||||
default_choices = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||
choices = [] + default_choices
|
||||
for func, name, description in self.get_actions(request).values():
|
||||
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
|
||||
# of most "choices" lists.
|
||||
# ToDo: write deprecation notice per Trac issue #35870.
|
||||
BLANK_CHOICE_DASH = [("", "---------")]
|
||||
|
||||
|
||||
@ -1056,7 +1057,7 @@ class Field(RegisterLookupMixin):
|
||||
def get_choices(
|
||||
self,
|
||||
include_blank=True,
|
||||
blank_choice=BLANK_CHOICE_DASH,
|
||||
blank_choice=None,
|
||||
limit_choices_to=None,
|
||||
ordering=(),
|
||||
):
|
||||
@ -1064,6 +1065,8 @@ class Field(RegisterLookupMixin):
|
||||
Return choices with a default blank choices included, for use
|
||||
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 include_blank:
|
||||
return BlankChoiceIterator(self.choices, blank_choice)
|
||||
|
@ -11,12 +11,12 @@ they're the closest concept currently available.
|
||||
|
||||
import warnings
|
||||
|
||||
from django.conf import settings
|
||||
from django.core import exceptions
|
||||
from django.utils.deprecation import RemovedInDjango60Warning
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.hashable import make_hashable
|
||||
|
||||
from . import BLANK_CHOICE_DASH
|
||||
from .mixins import FieldCacheMixin
|
||||
|
||||
|
||||
@ -175,7 +175,7 @@ class ForeignObjectRel(FieldCacheMixin):
|
||||
def get_choices(
|
||||
self,
|
||||
include_blank=True,
|
||||
blank_choice=BLANK_CHOICE_DASH,
|
||||
blank_choice=None,
|
||||
limit_choices_to=None,
|
||||
ordering=(),
|
||||
):
|
||||
@ -186,6 +186,8 @@ class ForeignObjectRel(FieldCacheMixin):
|
||||
Analog of django.db.models.fields.Field.get_choices(), provided
|
||||
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
|
||||
qs = self.related_model._default_manager.complex_filter(limit_choices_to)
|
||||
if ordering:
|
||||
|
@ -1217,7 +1217,7 @@ class FilePathField(ChoiceField):
|
||||
if self.required:
|
||||
self.choices = []
|
||||
else:
|
||||
self.choices = [("", "---------")]
|
||||
self.choices = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||
|
||||
if self.match is not None:
|
||||
self.match_re = re.compile(self.match)
|
||||
|
@ -5,6 +5,7 @@ and database field objects.
|
||||
|
||||
from itertools import chain
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import (
|
||||
NON_FIELD_ERRORS,
|
||||
FieldError,
|
||||
@ -1456,7 +1457,7 @@ class ModelChoiceField(ChoiceField):
|
||||
self,
|
||||
queryset,
|
||||
*,
|
||||
empty_label="---------",
|
||||
empty_label="",
|
||||
required=True,
|
||||
widget=None,
|
||||
label=None,
|
||||
@ -1483,6 +1484,8 @@ class ModelChoiceField(ChoiceField):
|
||||
):
|
||||
self.empty_label = None
|
||||
else:
|
||||
if empty_label == "":
|
||||
empty_label = settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL
|
||||
self.empty_label = empty_label
|
||||
self.queryset = queryset
|
||||
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
|
||||
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
|
||||
``empty_label`` to ``None``::
|
||||
|
||||
|
@ -234,7 +234,7 @@ documentation.
|
||||
.. _field-choices-blank-label:
|
||||
|
||||
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``
|
||||
containing ``None``; e.g. ``(None, 'Your String For Display')``.
|
||||
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
|
||||
<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
|
||||
|
||||
``FORMAT_MODULE_PATH``
|
||||
|
@ -294,7 +294,7 @@ class AdminActionsTest(TestCase):
|
||||
self.assertContains(
|
||||
response,
|
||||
"""<label>Action: <select name="action" required>
|
||||
<option value="" selected>---------</option>
|
||||
<option value="" selected>- Select an option -</option>
|
||||
<option value="delete_selected">Delete selected external
|
||||
subscribers</option>
|
||||
<option value="redirect_to">Redirect to (Awesome action)</option>
|
||||
|
@ -110,7 +110,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
self.assertHTMLEqual(
|
||||
fk_dropdown.get_attribute("innerHTML"),
|
||||
f"""
|
||||
<option value="" selected="">---------</option>
|
||||
<option value="" selected="">- Select an option -</option>
|
||||
<option value="{id_value}" selected>{interesting_name}</option>
|
||||
""",
|
||||
)
|
||||
@ -155,7 +155,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
self.assertHTMLEqual(
|
||||
fk_dropdown.get_attribute("innerHTML"),
|
||||
f"""
|
||||
<option value="" selected>---------</option>
|
||||
<option value="" selected>- Select an option -</option>
|
||||
<option value="{id_value}">{name}</option>
|
||||
""",
|
||||
)
|
||||
|
@ -7,6 +7,7 @@ from unittest import mock
|
||||
from urllib.parse import parse_qsl, urljoin, urlsplit
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib import admin
|
||||
from django.contrib.admin import AdminSite, ModelAdmin
|
||||
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])
|
||||
select = Select(self.selenium.find_element(By.ID, "id_parent"))
|
||||
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"), "")
|
||||
|
||||
def test_inline_with_popup_cancel_delete(self):
|
||||
@ -6696,7 +6699,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
self.assertHTMLEqual(
|
||||
_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>
|
||||
""",
|
||||
)
|
||||
@ -6715,7 +6718,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
# limit_choices_to.
|
||||
self.assertHTMLEqual(
|
||||
_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.
|
||||
@ -6734,7 +6737,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
self.assertHTMLEqual(
|
||||
_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="2">Spain</option>
|
||||
""",
|
||||
@ -6756,7 +6759,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
# limit_choices_to.
|
||||
self.assertHTMLEqual(
|
||||
_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.
|
||||
@ -6776,7 +6779,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
self.assertHTMLEqual(
|
||||
_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="2">Italy</option>
|
||||
""",
|
||||
@ -6796,7 +6799,7 @@ class SeleniumTests(AdminSeleniumTestCase):
|
||||
# favorite_country_to_vacation field has no options.
|
||||
self.assertHTMLEqual(
|
||||
_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.
|
||||
|
@ -1811,7 +1811,7 @@ class RelatedFieldWidgetSeleniumTests(AdminWidgetSeleniumTestCase):
|
||||
|
||||
# Chrome and Safari don't update related object links when selecting
|
||||
# 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.
|
||||
select = Select(self.selenium.find_element(By.ID, "id_user"))
|
||||
select.select_by_index(0)
|
||||
|
@ -1,5 +1,6 @@
|
||||
import decimal
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms import TypedChoiceField
|
||||
from django.test import SimpleTestCase
|
||||
@ -59,7 +60,11 @@ class TypedChoiceFieldTest(SimpleTestCase):
|
||||
self.assertFalse(f.has_changed("1", "1"))
|
||||
|
||||
f = TypedChoiceField(
|
||||
choices=[("", "---------"), ("a", "a"), ("b", "b")],
|
||||
choices=[
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
("a", "a"),
|
||||
("b", "b"),
|
||||
],
|
||||
coerce=str,
|
||||
required=False,
|
||||
initial=None,
|
||||
|
@ -1,12 +1,13 @@
|
||||
import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.forms import ChoiceField, Form, MultiWidget, RadioSelect, TextInput
|
||||
from django.test import override_settings
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
from .test_choicewidget import ChoiceWidgetTest
|
||||
|
||||
BLANK_CHOICE_DASH = (("", "------"),)
|
||||
BLANK_CHOICE = (("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),)
|
||||
|
||||
|
||||
class RadioSelectTest(ChoiceWidgetTest):
|
||||
@ -16,7 +17,9 @@ class RadioSelectTest(ChoiceWidgetTest):
|
||||
html = """
|
||||
<div>
|
||||
<div>
|
||||
<label><input type="radio" name="beatle" value="">------</label>
|
||||
<label>
|
||||
<input type="radio" name="beatle" value="">- Select an option -
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label><input checked type="radio" name="beatle" value="J">John</label>
|
||||
@ -32,7 +35,7 @@ class RadioSelectTest(ChoiceWidgetTest):
|
||||
</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)):
|
||||
with self.subTest(choices):
|
||||
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.
|
||||
"""
|
||||
choices = BLANK_CHOICE_DASH + self.beatles
|
||||
choices = BLANK_CHOICE + self.beatles
|
||||
html = """
|
||||
<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>
|
||||
<label><input type="radio" name="beatle" value="J">John</label>
|
||||
@ -463,11 +468,11 @@ class RadioSelectTest(ChoiceWidgetTest):
|
||||
|
||||
def test_render_as_subwidget(self):
|
||||
"""A RadioSelect as a subwidget of MultiWidget."""
|
||||
choices = BLANK_CHOICE_DASH + self.beatles
|
||||
choices = BLANK_CHOICE + self.beatles
|
||||
html = """
|
||||
<div>
|
||||
<div><label>
|
||||
<input type="radio" name="beatle_0" value="">------</label>
|
||||
<input type="radio" name="beatle_0" value="">- Select an option -</label>
|
||||
</div>
|
||||
<div><label>
|
||||
<input checked type="radio" name="beatle_0" value="J">John</label>
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError, models, transaction
|
||||
from django.test import SimpleTestCase, TestCase
|
||||
@ -48,7 +49,10 @@ class BooleanFieldTests(TestCase):
|
||||
"""
|
||||
choices = [(1, "Si"), (2, "No")]
|
||||
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):
|
||||
f = models.BooleanField(null=True)
|
||||
|
@ -1,6 +1,7 @@
|
||||
import pickle
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.test import SimpleTestCase, TestCase
|
||||
@ -354,7 +355,10 @@ class GetChoicesTests(SimpleTestCase):
|
||||
def test_lazy_strings_not_evaluated(self):
|
||||
lazy_func = lazy(lambda x: 0 / 0, int) # raises ZeroDivisionError if evaluated.
|
||||
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):
|
||||
|
@ -1,6 +1,7 @@
|
||||
import datetime
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.forms.models import ModelChoiceIterator, ModelChoiceIteratorValue
|
||||
from django.forms.widgets import CheckboxSelectMultiple
|
||||
@ -24,7 +25,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
(self.c3.pk, "Third"),
|
||||
@ -102,7 +103,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
],
|
||||
@ -118,7 +119,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(gen_two),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
],
|
||||
@ -130,7 +131,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "category Entertainment"),
|
||||
(self.c2.pk, "category A test"),
|
||||
(self.c3.pk, "category Third"),
|
||||
@ -143,7 +144,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
(self.c3.pk, "Third"),
|
||||
@ -154,7 +155,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
(self.c3.pk, "Third"),
|
||||
@ -174,6 +175,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertIs(bool(f.choices), True)
|
||||
|
||||
def test_choices_radio_blank(self):
|
||||
blank_choice = [("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)]
|
||||
choices = [
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
@ -190,7 +192,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
)
|
||||
self.assertEqual(
|
||||
list(f.choices),
|
||||
[("", "---------")] + choices if blank else choices,
|
||||
(blank_choice + choices if blank else choices),
|
||||
)
|
||||
|
||||
def test_deepcopies_widget(self):
|
||||
@ -425,7 +427,7 @@ class ModelChoiceFieldTests(TestCase):
|
||||
self.assertCountEqual(
|
||||
list(f.choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(self.c1.pk, "Entertainment"),
|
||||
(self.c2.pk, "A test"),
|
||||
(self.c3.pk, "Third"),
|
||||
|
@ -5,6 +5,7 @@ from decimal import Decimal
|
||||
from unittest import mock, skipUnless
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import (
|
||||
NON_FIELD_ERRORS,
|
||||
FieldError,
|
||||
@ -341,7 +342,7 @@ class ModelFormBaseTest(TestCase):
|
||||
self.assertEqual(
|
||||
list(form.fields["author"].choices),
|
||||
[
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(writer.pk, "Joe Doe"),
|
||||
],
|
||||
)
|
||||
@ -1534,7 +1535,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<li>Slug: <input type="text" name="slug" maxlength="50" required></li>
|
||||
<li>Pub date: <input type="text" name="pub_date" required></li>
|
||||
<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">Mike Royko</option>
|
||||
</select></li>
|
||||
@ -1546,7 +1547,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<option value="%s">Third test</option>
|
||||
</select></li>
|
||||
<li>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="3">Live</option>
|
||||
@ -1588,7 +1589,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<li>Pub date:
|
||||
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
||||
<li>Writer: <select name="writer" required>
|
||||
<option value="">---------</option>
|
||||
<option value="">- Select an option -</option>
|
||||
<option value="%s">Bob Woodward</option>
|
||||
<option value="%s" selected>Mike Royko</option>
|
||||
</select></li>
|
||||
@ -1600,7 +1601,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<option value="%s">Third test</option>
|
||||
</select></li>
|
||||
<li>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="3">Live</option>
|
||||
@ -1733,7 +1734,7 @@ class ModelFormBasicTests(TestCase):
|
||||
</div>
|
||||
<div>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">Mike Royko</option>
|
||||
</select>
|
||||
@ -1750,7 +1751,7 @@ class ModelFormBasicTests(TestCase):
|
||||
</div>
|
||||
<div>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="3">Live</option>
|
||||
</select>
|
||||
@ -1783,7 +1784,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<li>Pub date:
|
||||
<input type="text" name="pub_date" value="1988-01-04" required></li>
|
||||
<li>Writer: <select name="writer" required>
|
||||
<option value="">---------</option>
|
||||
<option value="">- Select an option -</option>
|
||||
<option value="%s">Bob Woodward</option>
|
||||
<option value="%s" selected>Mike Royko</option>
|
||||
</select></li>
|
||||
@ -1795,7 +1796,7 @@ class ModelFormBasicTests(TestCase):
|
||||
<option value="%s">Third test</option>
|
||||
</select></li>
|
||||
<li>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="3">Live</option>
|
||||
@ -1957,7 +1958,7 @@ class ModelFormBasicTests(TestCase):
|
||||
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
||||
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
||||
'<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">Mike Royko</option>'
|
||||
"</select></li>"
|
||||
@ -1969,7 +1970,7 @@ class ModelFormBasicTests(TestCase):
|
||||
'<option value="%s">Third test</option>'
|
||||
"</select> </li>"
|
||||
'<li>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="3">Live</option>'
|
||||
@ -1986,7 +1987,7 @@ class ModelFormBasicTests(TestCase):
|
||||
'<li>Slug: <input type="text" name="slug" maxlength="50" required></li>'
|
||||
'<li>Pub date: <input type="text" name="pub_date" required></li>'
|
||||
'<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">Carl Bernstein</option>'
|
||||
'<option value="%s">Mike Royko</option>'
|
||||
@ -2000,7 +2001,7 @@ class ModelFormBasicTests(TestCase):
|
||||
'<option value="%s">Fourth</option>'
|
||||
"</select></li>"
|
||||
'<li>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="3">Live</option>'
|
||||
@ -2044,7 +2045,8 @@ class ModelFormBasicTests(TestCase):
|
||||
self.assertEqual(call_count, 0)
|
||||
self.assertEqual(
|
||||
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)
|
||||
|
||||
@ -2410,7 +2412,7 @@ class ModelOneToOneFieldTests(TestCase):
|
||||
"""
|
||||
<p><label for="id_writer">Writer:</label>
|
||||
<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">Mike Royko</option>
|
||||
</select></p>
|
||||
@ -2437,7 +2439,7 @@ class ModelOneToOneFieldTests(TestCase):
|
||||
"""
|
||||
<p><label for="id_writer">Writer:</label>
|
||||
<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">Mike Royko</option>
|
||||
</select></p>
|
||||
@ -2726,7 +2728,8 @@ class FileAndImageFieldTests(TestCase):
|
||||
|
||||
form = FPForm()
|
||||
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")
|
||||
@ -3055,7 +3058,7 @@ class OtherModelFormTests(TestCase):
|
||||
self.assertEqual(
|
||||
tuple(field.choices),
|
||||
(
|
||||
("", "---------"),
|
||||
("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL),
|
||||
(multicolor_item.pk, "blue, red"),
|
||||
(red_item.pk, "red"),
|
||||
),
|
||||
@ -3069,14 +3072,19 @@ class OtherModelFormTests(TestCase):
|
||||
field = forms.ModelChoiceField(Inventory.objects.all(), to_field_name="barcode")
|
||||
self.assertEqual(
|
||||
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)
|
||||
self.assertHTMLEqual(
|
||||
str(form["parent"]),
|
||||
"""<select name="parent" id="id_parent">
|
||||
<option value="">---------</option>
|
||||
<option value="">- Select an option -</option>
|
||||
<option value="86" selected>Apple</option>
|
||||
<option value="87">Core</option>
|
||||
<option value="22">Pear</option>
|
||||
|
@ -1267,7 +1267,7 @@ class ModelFormsetTest(TestCase):
|
||||
formset.forms[0].as_p(),
|
||||
'<p><label for="id_form-0-owner">Owner:</label>'
|
||||
'<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">Jack Berry at Giordanos</option>'
|
||||
"</select></p>"
|
||||
|
@ -1,6 +1,7 @@
|
||||
from datetime import date
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.contrib.admin.models import ADDITION, CHANGE, DELETION, LogEntry
|
||||
from django.contrib.admin.options import (
|
||||
HORIZONTAL,
|
||||
@ -664,7 +665,7 @@ class ModelAdminTests(TestCase):
|
||||
'<div class="related-widget-wrapper" data-model-ref="band">'
|
||||
'<select data-context="available-source" '
|
||||
'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 Doors</option>'
|
||||
"</select></div>" % (band2.id, self.band.id),
|
||||
@ -688,7 +689,7 @@ class ModelAdminTests(TestCase):
|
||||
'<div class="related-widget-wrapper" data-model-ref="band">'
|
||||
'<select data-context="available-source" '
|
||||
'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>'
|
||||
"</select></div>" % self.band.id,
|
||||
)
|
||||
@ -736,29 +737,30 @@ class ModelAdminTests(TestCase):
|
||||
# ForeignKey widgets in the admin are wrapped with RelatedFieldWidgetWrapper so
|
||||
# they need to be handled properly when type checking. For Select fields, all of
|
||||
# the choices lists have a first entry of dashes.
|
||||
blank_option = ("", settings.FORMS_DEFAULT_BLANK_CHOICE_LABEL)
|
||||
cma = ModelAdmin(Concert, self.site)
|
||||
cmafa = cma.get_form(request)
|
||||
|
||||
self.assertEqual(type(cmafa.base_fields["main_band"].widget.widget), Select)
|
||||
self.assertEqual(
|
||||
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(
|
||||
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(
|
||||
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(
|
||||
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):
|
||||
|
Loading…
Reference in New Issue
Block a user