diff --git a/django/forms/fields.py b/django/forms/fields.py
index 7f0d26d..124e4f6 100644
a
|
b
|
class CharField(Field):
|
199 | 199 | |
200 | 200 | def widget_attrs(self, widget): |
201 | 201 | attrs = super(CharField, self).widget_attrs(widget) |
202 | | if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)): |
| 202 | if self.max_length is not None and isinstance(widget, TextInput): |
203 | 203 | # The HTML attribute is maxlength, not max_length. |
204 | 204 | attrs.update({'maxlength': str(self.max_length)}) |
205 | 205 | return attrs |
diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index 7651efc..f8af9e0 100644
a
|
b
|
class Input(Widget):
|
260 | 260 | final_attrs['value'] = force_text(self._format_value(value)) |
261 | 261 | return format_html('<input{0} />', flatatt(final_attrs)) |
262 | 262 | |
| 263 | |
263 | 264 | class TextInput(Input): |
264 | 265 | input_type = 'text' |
265 | 266 | |
266 | | class PasswordInput(Input): |
| 267 | def __init__(self, attrs=None, input_type=None): |
| 268 | if input_type is not None: |
| 269 | self.input_type = input_type |
| 270 | super(TextInput, self).__init__(attrs) |
| 271 | |
| 272 | |
| 273 | class PasswordInput(TextInput): |
267 | 274 | input_type = 'password' |
268 | 275 | |
269 | 276 | def __init__(self, attrs=None, render_value=False): |
… |
… |
class Textarea(Widget):
|
400 | 407 | flatatt(final_attrs), |
401 | 408 | force_text(value)) |
402 | 409 | |
403 | | class DateInput(Input): |
404 | | input_type = 'text' |
405 | 410 | |
406 | | def __init__(self, attrs=None, format=None): |
407 | | super(DateInput, self).__init__(attrs) |
| 411 | class DateInput(TextInput): |
| 412 | def __init__(self, attrs=None, format=None, **kwargs): |
| 413 | super(DateInput, self).__init__(attrs, **kwargs) |
408 | 414 | if format: |
409 | 415 | self.format = format |
410 | 416 | self.manual_format = True |
… |
… |
class DateInput(Input):
|
431 | 437 | pass |
432 | 438 | return super(DateInput, self)._has_changed(self._format_value(initial), data) |
433 | 439 | |
434 | | class DateTimeInput(Input): |
435 | | input_type = 'text' |
436 | 440 | |
437 | | def __init__(self, attrs=None, format=None): |
438 | | super(DateTimeInput, self).__init__(attrs) |
| 441 | class DateTimeInput(TextInput): |
| 442 | def __init__(self, attrs=None, format=None, **kwargs): |
| 443 | super(DateTimeInput, self).__init__(attrs, **kwargs) |
439 | 444 | if format: |
440 | 445 | self.format = format |
441 | 446 | self.manual_format = True |
… |
… |
class DateTimeInput(Input):
|
462 | 467 | pass |
463 | 468 | return super(DateTimeInput, self)._has_changed(self._format_value(initial), data) |
464 | 469 | |
465 | | class TimeInput(Input): |
466 | | input_type = 'text' |
467 | 470 | |
468 | | def __init__(self, attrs=None, format=None): |
469 | | super(TimeInput, self).__init__(attrs) |
| 471 | class TimeInput(TextInput): |
| 472 | def __init__(self, attrs=None, format=None, **kwargs): |
| 473 | super(TimeInput, self).__init__(attrs, **kwargs) |
470 | 474 | if format: |
471 | 475 | self.format = format |
472 | 476 | self.manual_format = True |
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index eab314a..96187e2 100644
a
|
b
|
commonly used groups of widgets:
|
178 | 178 | |
179 | 179 | Text input: ``<input type='text' ...>`` |
180 | 180 | |
| 181 | Takes one optional argument: |
| 182 | |
| 183 | .. attribute:: TextInput.input_type |
| 184 | |
| 185 | The content of the type attribute of the input element (defaults to |
| 186 | 'text'). |
| 187 | |
| 188 | .. versionchanged:: 1.5 |
| 189 | The `input_type` argument has been added |
| 190 | |
181 | 191 | ``PasswordInput`` |
182 | 192 | ~~~~~~~~~~~~~~~~~ |
183 | 193 | |
… |
… |
commonly used groups of widgets:
|
245 | 255 | |
246 | 256 | Date input as a simple text box: ``<input type='text' ...>`` |
247 | 257 | |
248 | | Takes one optional argument: |
| 258 | Takes same arguments as :class:`TextInput`, with one more optional argument: |
249 | 259 | |
250 | 260 | .. attribute:: DateInput.format |
251 | 261 | |
… |
… |
commonly used groups of widgets:
|
262 | 272 | |
263 | 273 | Date/time input as a simple text box: ``<input type='text' ...>`` |
264 | 274 | |
265 | | Takes one optional argument: |
| 275 | Takes same arguments as :class:`TextInput`, with one more optional argument: |
266 | 276 | |
267 | 277 | .. attribute:: DateTimeInput.format |
268 | 278 | |
… |
… |
commonly used groups of widgets:
|
279 | 289 | |
280 | 290 | Time input as a simple text box: ``<input type='text' ...>`` |
281 | 291 | |
282 | | Takes one optional argument: |
| 292 | Takes same arguments as :class:`TextInput`, with one more optional argument: |
283 | 293 | |
284 | 294 | .. attribute:: TimeInput.format |
285 | 295 | |
diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
index 544ca41..e062b9f 100644
a
|
b
|
class FormsWidgetTestCase(TestCase):
|
34 | 34 | w = TextInput(attrs={'class': 'fun'}) |
35 | 35 | self.assertHTMLEqual(w.render('email', ''), '<input type="text" class="fun" name="email" />') |
36 | 36 | self.assertHTMLEqual(w.render('email', 'foo@example.com'), '<input type="text" class="fun" value="foo@example.com" name="email" />') |
| 37 | # ... or input_type |
| 38 | w = TextInput(input_type='hello') |
| 39 | self.assertHTMLEqual(w.render('generic', ''), u'<input type="hello" name="generic" />') |
37 | 40 | |
38 | 41 | # 'attrs' passed to render() get precedence over those passed to the constructor: |
39 | 42 | w = TextInput(attrs={'class': 'pretty'}) |
… |
… |
beatle J R Ringo False""")
|
919 | 922 | self.assertHTMLEqual(w.render('date', d), '<input type="text" name="date" value="17/09/2007 12:51" />') |
920 | 923 | self.assertFalse(w._has_changed(d, '17/09/2007 12:51')) |
921 | 924 | |
| 925 | w = DateTimeInput(input_type='datetime') |
| 926 | self.assertHTMLEqual(w.render('date', None), '<input type="datetime" name="date" />') |
| 927 | |
922 | 928 | # Make sure a custom format works with _has_changed. The hidden input will use |
923 | 929 | data = datetime.datetime(2010, 3, 6, 12, 0, 0) |
924 | 930 | custom_format = '%d.%m.%Y %H:%M' |
… |
… |
beatle J R Ringo False""")
|
942 | 948 | self.assertHTMLEqual(w.render('date', d), '<input type="text" name="date" value="17/09/2007" />') |
943 | 949 | self.assertFalse(w._has_changed(d, '17/09/2007')) |
944 | 950 | |
| 951 | w = DateInput(input_type='date') |
| 952 | self.assertHTMLEqual(w.render('date', None), '<input type="date" name="date" />') |
| 953 | |
945 | 954 | # Make sure a custom format works with _has_changed. The hidden input will use |
946 | 955 | data = datetime.date(2010, 3, 6) |
947 | 956 | custom_format = '%d.%m.%Y' |
… |
… |
beatle J R Ringo False""")
|
967 | 976 | self.assertHTMLEqual(w.render('time', t), '<input type="text" name="time" value="12:51" />') |
968 | 977 | self.assertFalse(w._has_changed(t, '12:51')) |
969 | 978 | |
| 979 | w = DateInput(input_type='time') |
| 980 | self.assertHTMLEqual(w.render('time', None), '<input type="time" name="time" />') |
| 981 | |
970 | 982 | # Make sure a custom format works with _has_changed. The hidden input will use |
971 | 983 | data = datetime.time(13, 0) |
972 | 984 | custom_format = '%I:%M %p' |