| 14 | Specifying widgets |
| 15 | ------------------ |
| 16 | |
| 17 | Whenever you specify a field on a form, Django will use a default widget |
| 18 | that is appropriate to the type of data that is to be displayed. To find |
| 19 | which widget is used on which field, see the documentation about |
| 20 | :ref:`built-in fields`. |
| 21 | |
| 22 | However, if you want to use a different widget for a field, you can |
| 23 | just use the :attr:`~Field.widget` argument on the field definition. For example: |
| 24 | |
| 25 | .. code-block:: python |
| 26 | |
| 27 | from django import forms |
| 28 | |
| 29 | class CommentForm(forms.Form): |
| 30 | name = forms.CharField() |
| 31 | url = forms.URLField() |
| 32 | comment = forms.CharField(widget=forms.Textarea) |
| 33 | |
| 34 | This would specify a form with a comment that uses a larger Textarea widget, |
| 35 | rather than the default TextInput widget. |
| 36 | |
| 37 | |
| 38 | Setting arguments for widgets |
| 39 | ----------------------------- |
| 40 | |
| 41 | Some widgets take over arguments from the fields they represent, for example |
| 42 | :class:`RadioSelect` or :class:`MultipleChoiceField` will use the choices of |
| 43 | the underlying field. Some widgets have optional extra arguments; they can be |
| 44 | set when defining the widget on the field. The reference below describes which |
| 45 | options can be set. |
| 46 | |
| 47 | In this example, the :attr:`SelectDateWidget.years` attribute is set for a |
| 48 | :class:`~django.forms.widgets.extras.SelectDateWidget`: |
| 49 | |
| 50 | .. code-block:: python |
| 51 | |
| 52 | from django import forms |
| 53 | from django.forms.widgets.extras import SelectDateWidget |
| 54 | |
| 55 | YEAR_CHOICES = ('2010', '2009',) |
| 56 | RADIO_CHOICES = (('1','Radio 1',), ('2','Radio 2',),) |
| 57 | CHECKBOX_CHOICES = (('1','The first choice',), ('2','The Second Choice',),) |
| 58 | |
| 59 | class SimpleForm(forms.Form): |
| 60 | radio = forms.ChoiceField(widget=forms.RadioSelect, choices=RADIO_CHOICES) |
| 61 | checkboxes = forms.MultipleChoiceField(required=False, |
| 62 | widget=forms.CheckboxSelectMultiple, choices=CHECKBOX_CHOICES) |
| 63 | date = forms.DateField(widget=SelectDateWidget(years=YEAR_CHOICES)) |
| 64 | |
| 65 | |
| 66 | Widgets with choices |
| 67 | ^^^^^^^^^^^^^^^^^^^^ |
| 68 | |
| 69 | Widgets based on the :class:`Select` widget deal with choices. In the default |
| 70 | case these are "owned" by a field based on :class:`ChoiceField`. The |
| 71 | :class:`ChoiceField` dictates what the choices are and resets the choices on |
| 72 | the widget everytime they get changed on the field. |
| 73 | |
| 74 | Widgets which offer a ``choices`` attribute can however be used with fields |
| 75 | which are not based on choice - such as a :class:`TextField` - but it is |
| 76 | recommended to use a :class:`ChoiceField`-based field when the choices are |
| 77 | inherent to the model and not just the representational widget. |
| 78 | |
| 79 | Customizing widget instances |
| 80 | ---------------------------- |
| 81 | |
| 82 | When Django renders a widget as HTML, it only renders the bare minimum |
| 83 | HTML - Django doesn't add a class definition, or any other widget-specific |
| 84 | attributes. This means that all 'TextInput' widgets will appear the same |
| 85 | on your Web page. |
| 86 | |
| 87 | If you want to make one widget look different to another, you need to |
| 88 | specify additional attributes for each widget. When you specify a |
| 89 | widget, you can provide a list of attributes that will be added to the |
| 90 | rendered HTML for the widget. |
| 91 | |
| 92 | For example, take the following simple form: |
| 93 | |
| 94 | .. code-block:: python |
| 95 | |
| 96 | from django import forms |
| 97 | |
| 98 | class CommentForm(forms.Form): |
| 99 | name = forms.CharField() |
| 100 | url = forms.URLField() |
| 101 | comment = forms.CharField() |
| 102 | |
| 103 | This form will include three default TextInput widgets, with default rendering - |
| 104 | no CSS class, no extra attributes. This means that the input boxes provided for |
| 105 | each widget will be rendered exactly the same: |
| 106 | |
| 107 | .. code-block:: python |
| 108 | |
| 109 | >>> f = CommentForm(auto_id=False) |
| 110 | >>> f.as_table() |
| 111 | <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> |
| 112 | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
| 113 | <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> |
| 114 | |
| 115 | |
| 116 | On a real Web page, you probably don't want every widget to look the same. You |
| 117 | might want a larger input element for the comment, and you might want the 'name' |
| 118 | widget to have some special CSS class. To do this, you use the :attr:`Widget.attrs` |
| 119 | argument when creating the widget: |
| 120 | |
| 121 | For example: |
| 122 | |
| 123 | .. code-block:: python |
| 124 | |
| 125 | class CommentForm(forms.Form): |
| 126 | name = forms.CharField( |
| 127 | widget=forms.TextInput(attrs={'class':'special'})) |
| 128 | url = forms.URLField() |
| 129 | comment = forms.CharField( |
| 130 | widget=forms.TextInput(attrs={'size':'40'})) |
| 131 | |
| 132 | Django will then include the extra attributes in the rendered output: |
| 133 | |
| 134 | .. code-block:: python |
| 135 | |
| 136 | >>> f = CommentForm(auto_id=False) |
| 137 | >>> f.as_table() |
| 138 | <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> |
| 139 | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
| 140 | <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> |
| 141 | |
| 142 | Built-in widgets |
| 143 | ---------------- |
| 144 | |
153 | | Wrapper around multiple other widgets |
| 309 | Wrapper around multiple other widgets. |
| 310 | |
| 311 | Its ``render`` method is different than other widgets', because it has to |
| 312 | figure out how to split a single value for display in multiple widgets. |
| 313 | The ``value`` argument can be one of two things: |
| 314 | |
| 315 | * A list. |
| 316 | * A normal value (e.g., a string) that has been "compressed" from |
| 317 | a list of values. |
| 318 | |
| 319 | In the second case - i.e., if the value is NOT a list - render() will |
| 320 | first "decompress" the value into a list before rendering it. It does so by |
| 321 | calling the decompress() method, which MultiWidget subclasses must |
| 322 | implement. This method takes a single "compressed" value and returns a |
| 323 | list. |
| 324 | |
| 325 | When render() does its HTML rendering, each value in the list is rendered |
| 326 | with the corresponding widget - the first value is rendered in the first |
| 327 | widget, the second value is rendered in the second widget, etc. |
| 328 | |
| 329 | Subclasses may implement format_output(), which takes the list of rendered |
| 330 | widgets and returns a string of HTML that formats them any way you'd like. |
| 331 | |
| 332 | You'll probably want to use this class with :class:`MultiValueField`. |
| 333 | |
| 334 | .. attribute:: widgets |
| 335 | |
| 336 | An iterable containing the widgets needed. |
176 | | |
177 | | .. code-block:: python |
178 | | |
179 | | from django.forms.extras.widgets import SelectDateWidget |
180 | | |
181 | | date = forms.DateField(widget=SelectDateWidget()) |
182 | | |
183 | | Specifying widgets |
184 | | ------------------ |
185 | | .. currentmodule:: django.forms |
186 | | |
187 | | .. attribute:: Form.widget |
188 | | |
189 | | Whenever you specify a field on a form, Django will use a default widget |
190 | | that is appropriate to the type of data that is to be displayed. To find |
191 | | which widget is used on which field, see the documentation for the |
192 | | built-in Field classes. |
193 | | |
194 | | However, if you want to use a different widget for a field, you can - |
195 | | just use the 'widget' argument on the field definition. For example:: |
196 | | |
197 | | from django import forms |
198 | | |
199 | | class CommentForm(forms.Form): |
200 | | name = forms.CharField() |
201 | | url = forms.URLField() |
202 | | comment = forms.CharField(widget=forms.Textarea) |
203 | | |
204 | | This would specify a form with a comment that uses a larger Textarea widget, |
205 | | rather than the default TextInput widget. |
206 | | |
207 | | Customizing widget instances |
208 | | ---------------------------- |
209 | | |
210 | | When Django renders a widget as HTML, it only renders the bare minimum |
211 | | HTML - Django doesn't add a class definition, or any other widget-specific |
212 | | attributes. This means that all 'TextInput' widgets will appear the same |
213 | | on your Web page. |
214 | | |
215 | | If you want to make one widget look different to another, you need to |
216 | | specify additional attributes for each widget. When you specify a |
217 | | widget, you can provide a list of attributes that will be added to the |
218 | | rendered HTML for the widget. |
219 | | |
220 | | For example, take the following simple form:: |
221 | | |
222 | | class CommentForm(forms.Form): |
223 | | name = forms.CharField() |
224 | | url = forms.URLField() |
225 | | comment = forms.CharField() |
226 | | |
227 | | This form will include three default TextInput widgets, with default rendering - |
228 | | no CSS class, no extra attributes. This means that the input boxes provided for |
229 | | each widget will be rendered exactly the same:: |
230 | | |
231 | | >>> f = CommentForm(auto_id=False) |
232 | | >>> f.as_table() |
233 | | <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> |
234 | | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
235 | | <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> |
236 | | |
237 | | |
238 | | On a real Web page, you probably don't want every widget to look the same. You |
239 | | might want a larger input element for the comment, and you might want the 'name' |
240 | | widget to have some special CSS class. To do this, you use the ``attrs`` |
241 | | argument when creating the widget: |
242 | | |
243 | | .. attribute:: Widget.attrs |
244 | | |
245 | | For example:: |
246 | | |
247 | | class CommentForm(forms.Form): |
248 | | name = forms.CharField( |
249 | | widget=forms.TextInput(attrs={'class':'special'})) |
250 | | url = forms.URLField() |
251 | | comment = forms.CharField( |
252 | | widget=forms.TextInput(attrs={'size':'40'})) |
253 | | |
254 | | Django will then include the extra attributes in the rendered output:: |
255 | | |
256 | | >>> f = CommentForm(auto_id=False) |
257 | | >>> f.as_table() |
258 | | <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> |
259 | | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
260 | | <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> |