From da800be6ddfdd4c88b48011ef264ea1ec6365725 Mon Sep 17 00:00:00 2001 From: Loic Bistuer Date: Wed, 28 Aug 2013 13:22:47 +0700 Subject: [PATCH] Fixed #20986 -- Enabled SelectDateWidget to use custom months Reviewed by Trac alias MarkusH. --- django/forms/extras/widgets.py | 13 +++-- docs/ref/forms/widgets.txt | 17 +++++++ docs/releases/1.7.txt | 4 ++ tests/forms_tests/tests/test_extra.py | 70 +++++++++++++++++++++++++-- 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/django/forms/extras/widgets.py b/django/forms/extras/widgets.py index 0b96dc4153..5590a9806a 100644 --- a/django/forms/extras/widgets.py +++ b/django/forms/extras/widgets.py @@ -51,16 +51,23 @@ class SelectDateWidget(Widget): day_field = '%s_day' year_field = '%s_year' - def __init__(self, attrs=None, years=None, required=True): - # years is an optional list/tuple of years to use in the "year" select box. + def __init__(self, attrs=None, years=None, required=True, months=None): self.attrs = attrs or {} self.required = required + + # Optional list or tuple of years to use in the "year" select box. if years: self.years = years else: this_year = datetime.date.today().year self.years = range(this_year, this_year+10) + # Optional dict of months to use in the "month" select box. + if months: + self.months = months + else: + self.months = MONTHS + def render(self, name, value, attrs=None): try: year_val, month_val, day_val = value.year, value.month, value.day @@ -80,7 +87,7 @@ class SelectDateWidget(Widget): year_val, month_val, day_val = [int(v) for v in match.groups()] choices = [(i, i) for i in self.years] year_html = self.create_select(name, self.year_field, value, year_val, choices) - choices = list(six.iteritems(MONTHS)) + choices = list(six.iteritems(self.months)) month_html = self.create_select(name, self.month_field, value, month_val, choices) choices = [(i, i) for i in range(1, 32)] day_html = self.create_select(name, self.day_field, value, day_val, choices) diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt index 47e14043fc..efe947568e 100644 --- a/docs/ref/forms/widgets.txt +++ b/docs/ref/forms/widgets.txt @@ -763,3 +763,20 @@ Composite widgets An optional list/tuple of years to use in the "year" select box. The default is a list containing the current year and the next 9 years. + + .. attribute:: SelectDateWidget.months + + .. versionadded:: 1.7 + + An optional dict of months to use in the "months" select box. + + The keys of the dict correspond to the month number (1-indexed) and + the values are the displayed months. + + .. code-block:: python + + MONTHS = { + 1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'), + 5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'), + 9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec') + } diff --git a/docs/releases/1.7.txt b/docs/releases/1.7.txt index e057c49e78..2bf7c0258f 100644 --- a/docs/releases/1.7.txt +++ b/docs/releases/1.7.txt @@ -213,6 +213,10 @@ Forms return ``self.cleaned_data``. If it does return a changed dictionary then that will still be used. +* :attr:`SelectDateWidget.months + ` can be used to + customize the wording of the months displayed in the select widget. + Management Commands ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/forms_tests/tests/test_extra.py b/tests/forms_tests/tests/test_extra.py index 3bc22243fb..b86245ab73 100644 --- a/tests/forms_tests/tests/test_extra.py +++ b/tests/forms_tests/tests/test_extra.py @@ -10,6 +10,7 @@ from django.test import TestCase from django.test.utils import override_settings from django.utils import six from django.utils import translation +from django.utils.dates import MONTHS_AP from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible from .test_error_messages import AssertFormErrorsMixin @@ -32,6 +33,8 @@ class FormsExtraTestCase(TestCase, AssertFormErrorsMixin): # The forms library comes with some extra, higher-level Field and Widget def test_selectdate(self): w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016')) + + # Rendering the default state. self.assertHTMLEqual(w.render('mydate', ''), """""") + + # Rendering the None or '' values should yield the same output. self.assertHTMLEqual(w.render('mydate', None), w.render('mydate', '')) + # Rendering a string value. self.assertHTMLEqual(w.render('mydate', '2010-04-15'), """""") - # Accepts a datetime or a string: + # Rendering a datetime value. self.assertHTMLEqual(w.render('mydate', datetime.date(2010, 4, 15)), w.render('mydate', '2010-04-15')) - # Invalid dates still render the failed date: + # Invalid dates should still render the failed date. self.assertHTMLEqual(w.render('mydate', '2010-02-31'), """""") - # Using a SelectDateWidget in a form: + # Rendering with a custom months dict. + w = SelectDateWidget(months=MONTHS_AP, years=('2013',)) + self.assertHTMLEqual(w.render('mydate', ''), """ + + + +""") + + # Using a SelectDateWidget in a form. w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), required=False) self.assertHTMLEqual(w.render('mydate', ''), """