diff options
Diffstat (limited to 'tests/regressiontests/forms')
-rw-r--r-- | tests/regressiontests/forms/fields.py | 16 | ||||
-rw-r--r-- | tests/regressiontests/forms/forms.py | 52 | ||||
-rw-r--r-- | tests/regressiontests/forms/input_formats.py | 894 | ||||
-rw-r--r-- | tests/regressiontests/forms/localflavor/au.py | 2 | ||||
-rw-r--r-- | tests/regressiontests/forms/models.py | 100 | ||||
-rw-r--r-- | tests/regressiontests/forms/tests.py | 2 | ||||
-rw-r--r-- | tests/regressiontests/forms/widgets.py | 51 |
7 files changed, 1055 insertions, 62 deletions
diff --git a/tests/regressiontests/forms/fields.py b/tests/regressiontests/forms/fields.py index 990a9f74cf..e4f2c261c9 100644 --- a/tests/regressiontests/forms/fields.py +++ b/tests/regressiontests/forms/fields.py @@ -766,13 +766,13 @@ class FieldsTests(TestCase): # FilePathField ############################################################### def test_filepathfield_65(self): - path = forms.__file__ + path = os.path.abspath(forms.__file__) path = os.path.dirname(path) + '/' - assert fix_os_paths(path).endswith('/django/forms/') + self.assertTrue(fix_os_paths(path).endswith('/django/forms/')) def test_filepathfield_66(self): path = forms.__file__ - path = os.path.dirname(path) + '/' + path = os.path.dirname(os.path.abspath(path)) + '/' f = FilePathField(path=path) f.choices = [p for p in f.choices if p[0].endswith('.py')] f.choices.sort() @@ -787,13 +787,13 @@ class FieldsTests(TestCase): ] for exp, got in zip(expected, fix_os_paths(f.choices)): self.assertEqual(exp[1], got[1]) - assert got[0].endswith(exp[0]) + self.assertTrue(got[0].endswith(exp[0])) self.assertRaisesErrorWithMessage(ValidationError, "[u'Select a valid choice. fields.py is not one of the available choices.']", f.clean, 'fields.py') assert fix_os_paths(f.clean(path + 'fields.py')).endswith('/django/forms/fields.py') def test_filepathfield_67(self): path = forms.__file__ - path = os.path.dirname(path) + '/' + path = os.path.dirname(os.path.abspath(path)) + '/' f = FilePathField(path=path, match='^.*?\.py$') f.choices.sort() expected = [ @@ -807,10 +807,10 @@ class FieldsTests(TestCase): ] for exp, got in zip(expected, fix_os_paths(f.choices)): self.assertEqual(exp[1], got[1]) - assert got[0].endswith(exp[0]) + self.assertTrue(got[0].endswith(exp[0])) def test_filepathfield_68(self): - path = forms.__file__ + path = os.path.abspath(forms.__file__) path = os.path.dirname(path) + '/' f = FilePathField(path=path, recursive=True, match='^.*?\.py$') f.choices.sort() @@ -827,7 +827,7 @@ class FieldsTests(TestCase): ] for exp, got in zip(expected, fix_os_paths(f.choices)): self.assertEqual(exp[1], got[1]) - assert got[0].endswith(exp[0]) + self.assertTrue(got[0].endswith(exp[0])) # SplitDateTimeField ########################################################## diff --git a/tests/regressiontests/forms/forms.py b/tests/regressiontests/forms/forms.py index 58051fd133..91594139f2 100644 --- a/tests/regressiontests/forms/forms.py +++ b/tests/regressiontests/forms/forms.py @@ -522,6 +522,18 @@ tags. <input type="hidden" name="composers" value="P" /> <input type="hidden" name="composers" value="J" /> +DateTimeField rendered as_hidden() is special too + +>>> class MessageForm(Form): +... when = SplitDateTimeField() +>>> f = MessageForm({'when_0': '1992-01-01', 'when_1': '01:01'}) +>>> print f.is_valid() +True +>>> print f['when'] +<input type="text" name="when_0" value="1992-01-01" id="id_when_0" /><input type="text" name="when_1" value="01:01" id="id_when_1" /> +>>> print f['when'].as_hidden() +<input type="hidden" name="when_0" value="1992-01-01" id="id_when_0" /><input type="hidden" name="when_1" value="01:01" id="id_when_1" /> + MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. >>> class SongForm(Form): ... name = CharField() @@ -705,13 +717,13 @@ Form.clean() is required to return a dictionary of all clean data. >>> print f.as_table() <tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> <tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> -<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> +<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr> +<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr> >>> print f.as_ul() <li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> <li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li> -<li>Password1: <input type="password" name="password1" value="foo" /></li> -<li>Password2: <input type="password" name="password2" value="bar" /></li> +<li>Password1: <input type="password" name="password1" /></li> +<li>Password2: <input type="password" name="password2" /></li> >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) >>> f.errors {} @@ -1258,20 +1270,20 @@ to a Field class. This help text is displayed when a Form is rendered. ... password = CharField(widget=PasswordInput, help_text='Choose wisely.') >>> p = UserRegistration(auto_id=False) >>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> -<li>Password: <input type="password" name="password" /> Choose wisely.</li> +<li>Username: <input type="text" name="username" maxlength="10" /> <span class="helptext">e.g., user@example.com</span></li> +<li>Password: <input type="password" name="password" /> <span class="helptext">Choose wisely.</span></li> >>> print p.as_p() -<p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p> -<p>Password: <input type="password" name="password" /> Choose wisely.</p> +<p>Username: <input type="text" name="username" maxlength="10" /> <span class="helptext">e.g., user@example.com</span></p> +<p>Password: <input type="password" name="password" /> <span class="helptext">Choose wisely.</span></p> >>> print p.as_table() -<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr> -<tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr> +<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br /><span class="helptext">e.g., user@example.com</span></td></tr> +<tr><th>Password:</th><td><input type="password" name="password" /><br /><span class="helptext">Choose wisely.</span></td></tr> The help text is displayed whether or not data is provided for the form. >>> p = UserRegistration({'username': u'foo'}, auto_id=False) >>> print p.as_ul() -<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li> -<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li> +<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> <span class="helptext">e.g., user@example.com</span></li> +<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> <span class="helptext">Choose wisely.</span></li> help_text is not displayed for hidden fields. It can be used for documentation purposes, though. @@ -1281,7 +1293,7 @@ purposes, though. ... next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination') >>> p = UserRegistration(auto_id=False) >>> print p.as_ul() -<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> +<li>Username: <input type="text" name="username" maxlength="10" /> <span class="helptext">e.g., user@example.com</span></li> <li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li> Help text can include arbitrary Unicode characters. @@ -1289,7 +1301,7 @@ Help text can include arbitrary Unicode characters. ... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ') >>> p = UserRegistration(auto_id=False) >>> p.as_ul() -u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>' +u'<li>Username: <input type="text" name="username" maxlength="10" /> <span class="helptext">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</span></li>' # Subclassing forms ########################################################### @@ -1589,8 +1601,8 @@ Case 2: POST with erroneous data (a redisplayed form, with errors). <table> <tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> <tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters (it has 23).</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr> -<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> -<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> +<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr> +<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr> </table> <input type="submit" /> </form> @@ -1719,8 +1731,8 @@ the list of errors is empty). You can also use it in {% if %} statements. >>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) <form action=""> <p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> -<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> -<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<p><label>Password: <input type="password" name="password1" /></label></p> +<p><label>Password (again): <input type="password" name="password2" /></label></p> <input type="submit" /> </form> >>> t = Template('''<form action=""> @@ -1734,8 +1746,8 @@ the list of errors is empty). You can also use it in {% if %} statements. <form action=""> <ul class="errorlist"><li>Please make sure your passwords match.</li></ul> <p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> -<p><label>Password: <input type="password" name="password1" value="foo" /></label></p> -<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> +<p><label>Password: <input type="password" name="password1" /></label></p> +<p><label>Password (again): <input type="password" name="password2" /></label></p> <input type="submit" /> </form> diff --git a/tests/regressiontests/forms/input_formats.py b/tests/regressiontests/forms/input_formats.py new file mode 100644 index 0000000000..498c6de9fb --- /dev/null +++ b/tests/regressiontests/forms/input_formats.py @@ -0,0 +1,894 @@ +from datetime import time, date, datetime +from unittest import TestCase + +from django import forms +from django.conf import settings +from django.utils.translation import activate, deactivate + + +class LocalizedTimeTests(TestCase): + def setUp(self): + self.old_TIME_INPUT_FORMATS = settings.TIME_INPUT_FORMATS + self.old_USE_L10N = settings.USE_L10N + + settings.TIME_INPUT_FORMATS = ["%I:%M:%S %p", "%I:%M %p"] + settings.USE_L10N = True + + activate('de') + + def tearDown(self): + settings.TIME_INPUT_FORMATS = self.old_TIME_INPUT_FORMATS + settings.USE_L10N = self.old_USE_L10N + + deactivate() + + def test_timeField(self): + "TimeFields can parse dates in the default format" + f = forms.TimeField() + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30:05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '13:30:05') + + # Parse a time in a valid, but non-default format, get a parsed result + result = f.clean('13:30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_localized_timeField(self): + "Localized TimeFields act as unlocalized widgets" + f = forms.TimeField(localize=True) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30:05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_timeField_with_inputformat(self): + "TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%H.%M.%S", "%H.%M"]) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30.05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_localized_timeField_with_inputformat(self): + "Localized TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%H.%M.%S", "%H.%M"], localize=True) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30.05') + self.assertEqual(result, time(13,30,5)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + +class CustomTimeInputFormatsTests(TestCase): + def setUp(self): + self.old_TIME_INPUT_FORMATS = settings.TIME_INPUT_FORMATS + settings.TIME_INPUT_FORMATS = ["%I:%M:%S %p", "%I:%M %p"] + + def tearDown(self): + settings.TIME_INPUT_FORMATS = self.old_TIME_INPUT_FORMATS + + def test_timeField(self): + "TimeFields can parse dates in the default format" + f = forms.TimeField() + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30:05 PM') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '01:30:05 PM') + + # Parse a time in a valid, but non-default format, get a parsed result + result = f.clean('1:30 PM') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM") + + def test_localized_timeField(self): + "Localized TimeFields act as unlocalized widgets" + f = forms.TimeField(localize=True) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30:05 PM') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '01:30:05 PM') + + # Parse a time in a valid format, get a parsed result + result = f.clean('01:30 PM') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM") + + def test_timeField_with_inputformat(self): + "TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%H.%M.%S", "%H.%M"]) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30.05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:05 PM") + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM") + + def test_localized_timeField_with_inputformat(self): + "Localized TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%H.%M.%S", "%H.%M"], localize=True) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30.05') + self.assertEqual(result, time(13,30,5)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:05 PM") + + # Parse a time in a valid format, get a parsed result + result = f.clean('13.30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM") + + +class SimpleTimeFormatTests(TestCase): + def test_timeField(self): + "TimeFields can parse dates in the default format" + f = forms.TimeField() + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30:05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid, but non-default format, get a parsed result + result = f.clean('13:30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_localized_timeField(self): + "Localized TimeFields in a non-localized environment act as unlocalized widgets" + f = forms.TimeField() + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM') + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30:05') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid format, get a parsed result + result = f.clean('13:30') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_timeField_with_inputformat(self): + "TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%I:%M:%S %p", "%I:%M %p"]) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30:05 PM') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30 PM') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + def test_localized_timeField_with_inputformat(self): + "Localized TimeFields with manually specified input formats can accept those formats" + f = forms.TimeField(input_formats=["%I:%M:%S %p", "%I:%M %p"], localize=True) + # Parse a time in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05') + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30:05 PM') + self.assertEqual(result, time(13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:05") + + # Parse a time in a valid format, get a parsed result + result = f.clean('1:30 PM') + self.assertEqual(result, time(13,30,0)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "13:30:00") + + +class LocalizedDateTests(TestCase): + def setUp(self): + self.old_DATE_INPUT_FORMATS = settings.DATE_INPUT_FORMATS + self.old_USE_L10N = settings.USE_L10N + + settings.DATE_INPUT_FORMATS = ["%d/%m/%Y", "%d-%m-%Y"] + settings.USE_L10N = True + + activate('de') + + def tearDown(self): + settings.DATE_INPUT_FORMATS = self.old_DATE_INPUT_FORMATS + settings.USE_L10N = self.old_USE_L10N + + deactivate() + + def test_dateField(self): + "DateFields can parse dates in the default format" + f = forms.DateField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21/12/2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010') + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('21.12.10') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_localized_dateField(self): + "Localized DateFields act as unlocalized widgets" + f = forms.DateField(localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21/12/2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.10') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_dateField_with_inputformat(self): + "DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%m.%d.%Y", "%m-%d-%Y"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + self.assertRaises(forms.ValidationError, f.clean, '21/12/2010') + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_localized_dateField_with_inputformat(self): + "Localized DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%m.%d.%Y", "%m-%d-%Y"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + self.assertRaises(forms.ValidationError, f.clean, '21/12/2010') + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010') + self.assertEqual(result, date(2010,12,21)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + +class CustomDateInputFormatsTests(TestCase): + def setUp(self): + self.old_DATE_INPUT_FORMATS = settings.DATE_INPUT_FORMATS + settings.DATE_INPUT_FORMATS = ["%d.%m.%Y", "%d-%m-%Y"] + + def tearDown(self): + settings.DATE_INPUT_FORMATS = self.old_DATE_INPUT_FORMATS + + def test_dateField(self): + "DateFields can parse dates in the default format" + f = forms.DateField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010') + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('21-12-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_localized_dateField(self): + "Localized DateFields act as unlocalized widgets" + f = forms.DateField(localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21-12-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_dateField_with_inputformat(self): + "DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%m.%d.%Y", "%m-%d-%Y"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + def test_localized_dateField_with_inputformat(self): + "Localized DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%m.%d.%Y", "%m-%d-%Y"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010') + self.assertEqual(result, date(2010,12,21)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010") + +class SimpleDateFormatTests(TestCase): + def test_dateField(self): + "DateFields can parse dates in the default format" + f = forms.DateField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('2010-12-21') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('12/21/2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + def test_localized_dateField(self): + "Localized DateFields in a non-localized environment act as unlocalized widgets" + f = forms.DateField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('2010-12-21') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12/21/2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + def test_dateField_with_inputformat(self): + "DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%d.%m.%Y", "%d-%m-%Y"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + # Parse a date in a valid format, get a parsed result + result = f.clean('21-12-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + def test_localized_dateField_with_inputformat(self): + "Localized DateFields with manually specified input formats can accept those formats" + f = forms.DateField(input_formats=["%d.%m.%Y", "%d-%m-%Y"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + + # Parse a date in a valid format, get a parsed result + result = f.clean('21-12-2010') + self.assertEqual(result, date(2010,12,21)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21") + +class LocalizedDateTimeTests(TestCase): + def setUp(self): + self.old_DATETIME_INPUT_FORMATS = settings.DATETIME_INPUT_FORMATS + self.old_USE_L10N = settings.USE_L10N + + settings.DATETIME_INPUT_FORMATS = ["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"] + settings.USE_L10N = True + + activate('de') + + def tearDown(self): + settings.DATETIME_INPUT_FORMATS = self.old_DATETIME_INPUT_FORMATS + settings.USE_L10N = self.old_USE_L10N + + deactivate() + + def test_dateTimeField(self): + "DateTimeFields can parse dates in the default format" + f = forms.DateTimeField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM 21/12/2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010 13:30:05') + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('21.12.2010 13:30') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:00") + + def test_localized_dateTimeField(self): + "Localized DateTimeFields act as unlocalized widgets" + f = forms.DateTimeField(localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM 21/12/2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '21.12.2010 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('21.12.2010 13:30') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:00") + + def test_dateTimeField_with_inputformat(self): + "DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%H.%M.%S %m.%d.%Y", "%H.%M %m-%d-%Y"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05 13:30:05') + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM 21/12/2010') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('13.30.05 12.21.2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:05") + + # Parse a date in a valid format, get a parsed result + result = f.clean('13.30 12-21-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:00") + + def test_localized_dateTimeField_with_inputformat(self): + "Localized DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%H.%M.%S %m.%d.%Y", "%H.%M %m-%d-%Y"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + self.assertRaises(forms.ValidationError, f.clean, '1:30:05 PM 21/12/2010') + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('13.30.05 12.21.2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:05") + + # Parse a date in a valid format, get a parsed result + result = f.clean('13.30 12-21-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "21.12.2010 13:30:00") + + +class CustomDateTimeInputFormatsTests(TestCase): + def setUp(self): + self.old_DATETIME_INPUT_FORMATS = settings.DATETIME_INPUT_FORMATS + settings.DATETIME_INPUT_FORMATS = ["%I:%M:%S %p %d/%m/%Y", "%I:%M %p %d-%m-%Y"] + + def tearDown(self): + settings.DATETIME_INPUT_FORMATS = self.old_DATETIME_INPUT_FORMATS + + def test_dateTimeField(self): + "DateTimeFields can parse dates in the default format" + f = forms.DateTimeField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30:05 PM 21/12/2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip + text = f.widget._format_value(result) + self.assertEqual(text, '01:30:05 PM 21/12/2010') + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('1:30 PM 21-12-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM 21/12/2010") + + def test_localized_dateTimeField(self): + "Localized DateTimeFields act as unlocalized widgets" + f = forms.DateTimeField(localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30:05 PM 21/12/2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, '01:30:05 PM 21/12/2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30 PM 21-12-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM 21/12/2010") + + def test_dateTimeField_with_inputformat(self): + "DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%m.%d.%Y %H:%M:%S", "%m-%d-%Y %H:%M"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:05 PM 21/12/2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010 13:30') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM 21/12/2010") + + def test_localized_dateTimeField_with_inputformat(self): + "Localized DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%m.%d.%Y %H:%M:%S", "%m-%d-%Y %H:%M"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('12.21.2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:05 PM 21/12/2010") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12-21-2010 13:30') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "01:30:00 PM 21/12/2010") + +class SimpleDateTimeFormatTests(TestCase): + def test_dateTimeField(self): + "DateTimeFields can parse dates in the default format" + f = forms.DateTimeField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('2010-12-21 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + # Parse a date in a valid, but non-default format, get a parsed result + result = f.clean('12/21/2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + def test_localized_dateTimeField(self): + "Localized DateTimeFields in a non-localized environment act as unlocalized widgets" + f = forms.DateTimeField() + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '13:30:05 21.12.2010') + + # Parse a date in a valid format, get a parsed result + result = f.clean('2010-12-21 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + # Parse a date in a valid format, get a parsed result + result = f.clean('12/21/2010 13:30:05') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + def test_dateTimeField_with_inputformat(self): + "DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%I:%M:%S %p %d.%m.%Y", "%I:%M %p %d-%m-%Y"]) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30:05 PM 21.12.2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30 PM 21-12-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:00") + + def test_localized_dateTimeField_with_inputformat(self): + "Localized DateTimeFields with manually specified input formats can accept those formats" + f = forms.DateTimeField(input_formats=["%I:%M:%S %p %d.%m.%Y", "%I:%M %p %d-%m-%Y"], localize=True) + # Parse a date in an unaccepted format; get an error + self.assertRaises(forms.ValidationError, f.clean, '2010-12-21 13:30:05') + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30:05 PM 21.12.2010') + self.assertEqual(result, datetime(2010,12,21,13,30,5)) + + # Check that the parsed result does a round trip to the same format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:05") + + # Parse a date in a valid format, get a parsed result + result = f.clean('1:30 PM 21-12-2010') + self.assertEqual(result, datetime(2010,12,21,13,30)) + + # Check that the parsed result does a round trip to default format + text = f.widget._format_value(result) + self.assertEqual(text, "2010-12-21 13:30:00") diff --git a/tests/regressiontests/forms/localflavor/au.py b/tests/regressiontests/forms/localflavor/au.py index fd4c0d6980..cda782094a 100644 --- a/tests/regressiontests/forms/localflavor/au.py +++ b/tests/regressiontests/forms/localflavor/au.py @@ -50,7 +50,7 @@ u'' ## AUPhoneNumberField ######################################################## A field that accepts a 10 digit Australian phone number. -llows spaces and parentheses around area code. +Allows spaces and parentheses around area code. >>> from django.contrib.localflavor.au.forms import AUPhoneNumberField >>> f = AUPhoneNumberField() diff --git a/tests/regressiontests/forms/models.py b/tests/regressiontests/forms/models.py index 229c50556e..028ff9bad2 100644 --- a/tests/regressiontests/forms/models.py +++ b/tests/regressiontests/forms/models.py @@ -38,11 +38,28 @@ class ChoiceOptionModel(models.Model): Can't reuse ChoiceModel because error_message tests require that it have no instances.""" name = models.CharField(max_length=10) + class Meta: + ordering = ('name',) + + def __unicode__(self): + return u'ChoiceOption %d' % self.pk + class ChoiceFieldModel(models.Model): """Model with ForeignKey to another model, for testing ModelForm generation with ModelChoiceField.""" choice = models.ForeignKey(ChoiceOptionModel, blank=False, - default=lambda: ChoiceOptionModel.objects.all()[0]) + default=lambda: ChoiceOptionModel.objects.get(name='default')) + choice_int = models.ForeignKey(ChoiceOptionModel, blank=False, related_name='choice_int', + default=lambda: 1) + + multi_choice = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice', + default=lambda: ChoiceOptionModel.objects.filter(name='default')) + multi_choice_int = models.ManyToManyField(ChoiceOptionModel, blank=False, related_name='multi_choice_int', + default=lambda: [1]) + +class ChoiceFieldForm(django_forms.ModelForm): + class Meta: + model = ChoiceFieldModel class FileModel(models.Model): file = models.FileField(storage=temp_storage, upload_to='tests') @@ -74,6 +91,74 @@ class TestTicket12510(TestCase): # only one query is required to pull the model from DB self.assertEqual(initial_queries+1, len(connection.queries)) +class ModelFormCallableModelDefault(TestCase): + def test_no_empty_option(self): + "If a model's ForeignKey has blank=False and a default, no empty option is created (Refs #10792)." + option = ChoiceOptionModel.objects.create(name='default') + + choices = list(ChoiceFieldForm().fields['choice'].choices) + self.assertEquals(len(choices), 1) + self.assertEquals(choices[0], (option.pk, unicode(option))) + + def test_callable_initial_value(self): + "The initial value for a callable default returning a queryset is the pk (refs #13769)" + obj1 = ChoiceOptionModel.objects.create(id=1, name='default') + obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') + obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') + self.assertEquals(ChoiceFieldForm().as_p(), """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice"> +<option value="1" selected="selected">ChoiceOption 1</option> +<option value="2">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-choice" value="1" id="initial-id_choice" /></p> +<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int"> +<option value="1" selected="selected">ChoiceOption 1</option> +<option value="2">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-choice_int" value="1" id="initial-id_choice_int" /></p> +<p><label for="id_multi_choice">Multi choice:</label> <select multiple="multiple" name="multi_choice" id="id_multi_choice"> +<option value="1" selected="selected">ChoiceOption 1</option> +<option value="2">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-multi_choice" value="1" id="initial-id_multi_choice_0" /> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p> +<p><label for="id_multi_choice_int">Multi choice int:</label> <select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int"> +<option value="1" selected="selected">ChoiceOption 1</option> +<option value="2">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-multi_choice_int" value="1" id="initial-id_multi_choice_int_0" /> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p>""") + + def test_initial_instance_value(self): + "Initial instances for model fields may also be instances (refs #7287)" + obj1 = ChoiceOptionModel.objects.create(id=1, name='default') + obj2 = ChoiceOptionModel.objects.create(id=2, name='option 2') + obj3 = ChoiceOptionModel.objects.create(id=3, name='option 3') + self.assertEquals(ChoiceFieldForm(initial={ + 'choice': obj2, + 'choice_int': obj2, + 'multi_choice': [obj2,obj3], + 'multi_choice_int': ChoiceOptionModel.objects.exclude(name="default"), + }).as_p(), """<p><label for="id_choice">Choice:</label> <select name="choice" id="id_choice"> +<option value="1">ChoiceOption 1</option> +<option value="2" selected="selected">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-choice" value="2" id="initial-id_choice" /></p> +<p><label for="id_choice_int">Choice int:</label> <select name="choice_int" id="id_choice_int"> +<option value="1">ChoiceOption 1</option> +<option value="2" selected="selected">ChoiceOption 2</option> +<option value="3">ChoiceOption 3</option> +</select><input type="hidden" name="initial-choice_int" value="2" id="initial-id_choice_int" /></p> +<p><label for="id_multi_choice">Multi choice:</label> <select multiple="multiple" name="multi_choice" id="id_multi_choice"> +<option value="1">ChoiceOption 1</option> +<option value="2" selected="selected">ChoiceOption 2</option> +<option value="3" selected="selected">ChoiceOption 3</option> +</select><input type="hidden" name="initial-multi_choice" value="2" id="initial-id_multi_choice_0" /> +<input type="hidden" name="initial-multi_choice" value="3" id="initial-id_multi_choice_1" /> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p> +<p><label for="id_multi_choice_int">Multi choice int:</label> <select multiple="multiple" name="multi_choice_int" id="id_multi_choice_int"> +<option value="1">ChoiceOption 1</option> +<option value="2" selected="selected">ChoiceOption 2</option> +<option value="3" selected="selected">ChoiceOption 3</option> +</select><input type="hidden" name="initial-multi_choice_int" value="2" id="initial-id_multi_choice_int_0" /> +<input type="hidden" name="initial-multi_choice_int" value="3" id="initial-id_multi_choice_int_1" /> <span class="helptext"> Hold down "Control", or "Command" on a Mac, to select more than one.</span></p>""") + __test__ = {'API_TESTS': """ >>> from django.forms.models import ModelForm @@ -155,18 +240,5 @@ u'class default value' datetime.date(1999, 3, 2) >>> shutil.rmtree(temp_storage_location) -In a ModelForm with a ModelChoiceField, if the model's ForeignKey has blank=False and a default, -no empty option is created (regression test for #10792). - -First we need at least one instance of ChoiceOptionModel: - ->>> ChoiceOptionModel.objects.create(name='default') -<ChoiceOptionModel: ChoiceOptionModel object> - ->>> class ChoiceFieldForm(ModelForm): -... class Meta: -... model = ChoiceFieldModel ->>> list(ChoiceFieldForm().fields['choice'].choices) -[(1, u'ChoiceOptionModel object')] """} diff --git a/tests/regressiontests/forms/tests.py b/tests/regressiontests/forms/tests.py index 8757e799a9..7a91cb701e 100644 --- a/tests/regressiontests/forms/tests.py +++ b/tests/regressiontests/forms/tests.py @@ -41,6 +41,8 @@ from fields import FieldsTests from validators import TestFieldWithValidators from widgets import WidgetTests +from input_formats import * + __test__ = { 'extra_tests': extra_tests, 'form_tests': form_tests, diff --git a/tests/regressiontests/forms/widgets.py b/tests/regressiontests/forms/widgets.py index 39d7d569a3..59b33d5210 100644 --- a/tests/regressiontests/forms/widgets.py +++ b/tests/regressiontests/forms/widgets.py @@ -62,6 +62,17 @@ u'<input type="text" class="special" name="email" />' u'<input type="password" name="email" />' >>> w.render('email', None) u'<input type="password" name="email" />' +>>> w.render('email', 'secret') +u'<input type="password" name="email" />' + +The render_value argument lets you specify whether the widget should render +its value. For security reasons, this is off by default. + +>>> w = PasswordInput(render_value=True) +>>> w.render('email', '') +u'<input type="password" name="email" />' +>>> w.render('email', None) +u'<input type="password" name="email" />' >>> w.render('email', 'test@example.com') u'<input type="password" name="email" value="test@example.com" />' >>> w.render('email', 'some "quoted" & ampersanded value') @@ -70,36 +81,20 @@ u'<input type="password" name="email" value="some "quoted" & amper u'<input type="password" name="email" value="test@example.com" class="fun" />' You can also pass 'attrs' to the constructor: ->>> w = PasswordInput(attrs={'class': 'fun'}) +>>> w = PasswordInput(attrs={'class': 'fun'}, render_value=True) >>> w.render('email', '') u'<input type="password" class="fun" name="email" />' >>> w.render('email', 'foo@example.com') u'<input type="password" class="fun" value="foo@example.com" name="email" />' 'attrs' passed to render() get precedence over those passed to the constructor: ->>> w = PasswordInput(attrs={'class': 'pretty'}) +>>> w = PasswordInput(attrs={'class': 'pretty'}, render_value=True) >>> w.render('email', '', attrs={'class': 'special'}) u'<input type="password" class="special" name="email" />' >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' -The render_value argument lets you specify whether the widget should render -its value. You may want to do this for security reasons. ->>> w = PasswordInput(render_value=True) ->>> w.render('email', 'secret') -u'<input type="password" name="email" value="secret" />' ->>> w = PasswordInput(render_value=False) ->>> w.render('email', '') -u'<input type="password" name="email" />' ->>> w.render('email', None) -u'<input type="password" name="email" />' ->>> w.render('email', 'secret') -u'<input type="password" name="email" />' ->>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False) ->>> w.render('email', 'secret') -u'<input type="password" class="fun" name="email" />' - # HiddenInput Widget ############################################################ >>> w = HiddenInput() @@ -1286,7 +1281,7 @@ class SelectAndTextWidget(forms.MultiWidget): forms.TextInput ] super(SelectAndTextWidget, self).__init__(widgets) - + def _set_choices(self, choices): """ When choices are set for this widget, we want to pass those along to the Select widget @@ -1310,3 +1305,21 @@ class WidgetTests(TestCase): # w2 ought to be independent of w1, since MultiWidget ought # to make a copy of its sub-widgets when it is copied. self.assertEqual(w1.choices, [1,2,3]) + + def test_13390(self): + # See ticket #13390 + class SplitDateForm(forms.Form): + field = forms.DateTimeField(widget=forms.SplitDateTimeWidget, required=False) + + form = SplitDateForm({'field': ''}) + self.assertTrue(form.is_valid()) + form = SplitDateForm({'field': ['', '']}) + self.assertTrue(form.is_valid()) + + class SplitDateRequiredForm(forms.Form): + field = forms.DateTimeField(widget=forms.SplitDateTimeWidget, required=True) + + form = SplitDateRequiredForm({'field': ''}) + self.assertFalse(form.is_valid()) + form = SplitDateRequiredForm({'field': ['', '']}) + self.assertFalse(form.is_valid()) |