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' |