Code

Ticket #16630: 16630-input_type.diff

File 16630-input_type.diff, 6.7 KB (added by claudep, 20 months ago)

Made input_type customizable

Line 
1diff --git a/django/forms/fields.py b/django/forms/fields.py
2index 7f0d26d..124e4f6 100644
3--- a/django/forms/fields.py
4+++ b/django/forms/fields.py
5@@ -199,7 +199,7 @@ class CharField(Field):
6 
7     def widget_attrs(self, widget):
8         attrs = super(CharField, self).widget_attrs(widget)
9-        if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
10+        if self.max_length is not None and isinstance(widget, TextInput):
11             # The HTML attribute is maxlength, not max_length.
12             attrs.update({'maxlength': str(self.max_length)})
13         return attrs
14diff --git a/django/forms/widgets.py b/django/forms/widgets.py
15index 7651efc..f8af9e0 100644
16--- a/django/forms/widgets.py
17+++ b/django/forms/widgets.py
18@@ -260,10 +260,17 @@ class Input(Widget):
19             final_attrs['value'] = force_text(self._format_value(value))
20         return format_html('<input{0} />', flatatt(final_attrs))
21 
22+
23 class TextInput(Input):
24     input_type = 'text'
25 
26-class PasswordInput(Input):
27+    def __init__(self, attrs=None, input_type=None):
28+        if input_type is not None:
29+            self.input_type = input_type
30+        super(TextInput, self).__init__(attrs)
31+
32+
33+class PasswordInput(TextInput):
34     input_type = 'password'
35 
36     def __init__(self, attrs=None, render_value=False):
37@@ -400,11 +407,10 @@ class Textarea(Widget):
38                            flatatt(final_attrs),
39                            force_text(value))
40 
41-class DateInput(Input):
42-    input_type = 'text'
43 
44-    def __init__(self, attrs=None, format=None):
45-        super(DateInput, self).__init__(attrs)
46+class DateInput(TextInput):
47+    def __init__(self, attrs=None, format=None, **kwargs):
48+        super(DateInput, self).__init__(attrs, **kwargs)
49         if format:
50             self.format = format
51             self.manual_format = True
52@@ -431,11 +437,10 @@ class DateInput(Input):
53             pass
54         return super(DateInput, self)._has_changed(self._format_value(initial), data)
55 
56-class DateTimeInput(Input):
57-    input_type = 'text'
58 
59-    def __init__(self, attrs=None, format=None):
60-        super(DateTimeInput, self).__init__(attrs)
61+class DateTimeInput(TextInput):
62+    def __init__(self, attrs=None, format=None, **kwargs):
63+        super(DateTimeInput, self).__init__(attrs, **kwargs)
64         if format:
65             self.format = format
66             self.manual_format = True
67@@ -462,11 +467,10 @@ class DateTimeInput(Input):
68             pass
69         return super(DateTimeInput, self)._has_changed(self._format_value(initial), data)
70 
71-class TimeInput(Input):
72-    input_type = 'text'
73 
74-    def __init__(self, attrs=None, format=None):
75-        super(TimeInput, self).__init__(attrs)
76+class TimeInput(TextInput):
77+    def __init__(self, attrs=None, format=None, **kwargs):
78+        super(TimeInput, self).__init__(attrs, **kwargs)
79         if format:
80             self.format = format
81             self.manual_format = True
82diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
83index eab314a..96187e2 100644
84--- a/docs/ref/forms/widgets.txt
85+++ b/docs/ref/forms/widgets.txt
86@@ -178,6 +178,16 @@ commonly used groups of widgets:
87 
88     Text input: ``<input type='text' ...>``
89 
90+    Takes one optional argument:
91+
92+    .. attribute:: TextInput.input_type
93+
94+        The content of the type attribute of the input element (defaults to
95+        'text').
96+
97+    .. versionchanged:: 1.5
98+        The `input_type` argument has been added
99+
100 ``PasswordInput``
101 ~~~~~~~~~~~~~~~~~
102 
103@@ -245,7 +255,7 @@ commonly used groups of widgets:
104 
105     Date input as a simple text box: ``<input type='text' ...>``
106 
107-    Takes one optional argument:
108+    Takes same arguments as :class:`TextInput`, with one more optional argument:
109 
110     .. attribute:: DateInput.format
111 
112@@ -262,7 +272,7 @@ commonly used groups of widgets:
113 
114     Date/time input as a simple text box: ``<input type='text' ...>``
115 
116-    Takes one optional argument:
117+    Takes same arguments as :class:`TextInput`, with one more optional argument:
118 
119     .. attribute:: DateTimeInput.format
120 
121@@ -279,7 +289,7 @@ commonly used groups of widgets:
122 
123     Time input as a simple text box: ``<input type='text' ...>``
124 
125-    Takes one optional argument:
126+    Takes same arguments as :class:`TextInput`, with one more optional argument:
127 
128     .. attribute:: TimeInput.format
129 
130diff --git a/tests/regressiontests/forms/tests/widgets.py b/tests/regressiontests/forms/tests/widgets.py
131index 544ca41..e062b9f 100644
132--- a/tests/regressiontests/forms/tests/widgets.py
133+++ b/tests/regressiontests/forms/tests/widgets.py
134@@ -34,6 +34,9 @@ class FormsWidgetTestCase(TestCase):
135         w = TextInput(attrs={'class': 'fun'})
136         self.assertHTMLEqual(w.render('email', ''), '<input type="text" class="fun" name="email" />')
137         self.assertHTMLEqual(w.render('email', 'foo@example.com'), '<input type="text" class="fun" value="foo@example.com" name="email" />')
138+        # ... or input_type
139+        w = TextInput(input_type='hello')
140+        self.assertHTMLEqual(w.render('generic', ''), u'<input type="hello" name="generic" />')
141 
142         # 'attrs' passed to render() get precedence over those passed to the constructor:
143         w = TextInput(attrs={'class': 'pretty'})
144@@ -919,6 +922,9 @@ beatle J R Ringo False""")
145         self.assertHTMLEqual(w.render('date', d), '<input type="text" name="date" value="17/09/2007 12:51" />')
146         self.assertFalse(w._has_changed(d, '17/09/2007 12:51'))
147 
148+        w = DateTimeInput(input_type='datetime')
149+        self.assertHTMLEqual(w.render('date', None), '<input type="datetime" name="date" />')
150+
151         # Make sure a custom format works with _has_changed. The hidden input will use
152         data = datetime.datetime(2010, 3, 6, 12, 0, 0)
153         custom_format = '%d.%m.%Y %H:%M'
154@@ -942,6 +948,9 @@ beatle J R Ringo False""")
155         self.assertHTMLEqual(w.render('date', d), '<input type="text" name="date" value="17/09/2007" />')
156         self.assertFalse(w._has_changed(d, '17/09/2007'))
157 
158+        w = DateInput(input_type='date')
159+        self.assertHTMLEqual(w.render('date', None), '<input type="date" name="date" />')
160+
161         # Make sure a custom format works with _has_changed. The hidden input will use
162         data = datetime.date(2010, 3, 6)
163         custom_format = '%d.%m.%Y'
164@@ -967,6 +976,9 @@ beatle J R Ringo False""")
165         self.assertHTMLEqual(w.render('time', t), '<input type="text" name="time" value="12:51" />')
166         self.assertFalse(w._has_changed(t, '12:51'))
167 
168+        w = DateInput(input_type='time')
169+        self.assertHTMLEqual(w.render('time', None), '<input type="time" name="time" />')
170+
171         # Make sure a custom format works with _has_changed. The hidden input will use
172         data = datetime.time(13, 0)
173         custom_format = '%I:%M %p'