diff --git a/django/forms/extras/widgets.py b/django/forms/extras/widgets.py
index 09d22b0fb5..0d63b177f7 100644
--- a/django/forms/extras/widgets.py
+++ b/django/forms/extras/widgets.py
@@ -64,8 +64,21 @@ class SelectDateWidget(Widget):
else:
self.months = MONTHS
- if empty_label is not None:
- self.none_value = (0, empty_label)
+ # Optional string, list, or tuple to use as empty_label.
+ if isinstance(empty_label, (list, tuple)):
+ if not len(empty_label) == 3:
+ raise ValueError('empty_label list/tuple must have 3 elements.')
+
+ self.year_none_value = (0, empty_label[0])
+ self.month_none_value = (0, empty_label[1])
+ self.day_none_value = (0, empty_label[2])
+ else:
+ if empty_label is not None:
+ self.none_value = (0, empty_label)
+
+ self.year_none_value = self.none_value
+ self.month_none_value = self.none_value
+ self.day_none_value = self.none_value
def render(self, name, value, attrs=None):
try:
@@ -86,11 +99,11 @@ class SelectDateWidget(Widget):
year_val, month_val, day_val = [int(v) for v in match.groups()]
html = {}
choices = [(i, i) for i in self.years]
- html['year'] = self.create_select(name, self.year_field, value, year_val, choices)
+ html['year'] = self.create_select(name, self.year_field, value, year_val, choices, self.year_none_value)
choices = list(six.iteritems(self.months))
- html['month'] = self.create_select(name, self.month_field, value, month_val, choices)
+ html['month'] = self.create_select(name, self.month_field, value, month_val, choices, self.month_none_value)
choices = [(i, i) for i in range(1, 32)]
- html['day'] = self.create_select(name, self.day_field, value, day_val, choices)
+ html['day'] = self.create_select(name, self.day_field, value, day_val, choices, self.day_none_value)
output = []
for field in _parse_date_fmt():
@@ -123,13 +136,13 @@ class SelectDateWidget(Widget):
return '%s-%s-%s' % (y, m, d)
return data.get(name, None)
- def create_select(self, name, field, value, val, choices):
+ def create_select(self, name, field, value, val, choices, none_value):
if 'id' in self.attrs:
id_ = self.attrs['id']
else:
id_ = 'id_%s' % name
if not self.is_required:
- choices.insert(0, self.none_value)
+ choices.insert(0, none_value)
local_attrs = self.build_attrs(id=field % id_)
s = Select(choices=choices)
select_html = s.render(field % name, val, local_attrs)
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index cf309f0298..7ed235b9e3 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -787,9 +787,20 @@ Composite widgets
.. versionadded:: 1.8
If the :class:`~django.forms.DateField` is not required,
- :class:`SelectDateWidget` 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`` attribute::
+ :class:`SelectDateWidget` will have an empty choice at the top of the
+ list (which is ``---`` by default). You can change the text of this
+ label with the ``empty_label`` attribute. ``empty_label`` can be a
+ ``string``, ``list``, or ``tuple``. When a string is used, all select
+ boxes will each have an empty choice with this label. If ``empty_label``
+ is a ``list`` or ``tuple`` of 3 string elements, the select boxes will
+ have their own custom label. The labels should be in this order
+ ``('year_label', 'month_label', 'day_label')``.
- # A custom empty label
+ .. code-block:: python
+
+ # A custom empty label with string
field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing"))
+
+ # A custom empty label with tuple
+ field1 = forms.DateField(widget=SelectDateWidget(
+ empty_label=("Choose Year", "Choose Month", "Choose Day"))
diff --git a/tests/forms_tests/tests/test_extra.py b/tests/forms_tests/tests/test_extra.py
index 499db79014..3f6208fade 100644
--- a/tests/forms_tests/tests/test_extra.py
+++ b/tests/forms_tests/tests/test_extra.py
@@ -297,11 +297,6 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
""")
- w = SelectDateWidget(years=('2014',), empty_label='empty_label')
-
- # Rendering the default state with empty_label setted.
- self.assertInHTML('', w.render('mydate', ''), count=3)
-
a = GetDate({'mydate_month': '4', 'mydate_day': '1', 'mydate_year': '2008'})
self.assertTrue(a.is_valid())
self.assertEqual(a.cleaned_data['mydate'], datetime.date(2008, 4, 1))
@@ -325,6 +320,72 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin):
d = GetDate({'mydate_month': '1', 'mydate_day': '1', 'mydate_year': '2010'})
self.assertTrue('