summaryrefslogtreecommitdiff
path: root/tests/regressiontests/forms
diff options
context:
space:
mode:
Diffstat (limited to 'tests/regressiontests/forms')
-rw-r--r--tests/regressiontests/forms/fields.py16
-rw-r--r--tests/regressiontests/forms/forms.py52
-rw-r--r--tests/regressiontests/forms/input_formats.py894
-rw-r--r--tests/regressiontests/forms/localflavor/au.py2
-rw-r--r--tests/regressiontests/forms/models.py100
-rw-r--r--tests/regressiontests/forms/tests.py2
-rw-r--r--tests/regressiontests/forms/widgets.py51
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 &quot;quoted&quot; &amp; 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())