| | 1440 | Widgets |
|---|
| | 1441 | ======= |
|---|
| | 1442 | |
|---|
| | 1443 | A widget is Django's representation of a HTML input element. The widget |
|---|
| | 1444 | handles the rendering of the HTML, and the extraction of data from a GET/POST |
|---|
| | 1445 | dictionary that corresponds to the widget. |
|---|
| | 1446 | |
|---|
| | 1447 | Django provides a representation of all the basic HTML widgets, plus some |
|---|
| | 1448 | commonly used groups of widgets: |
|---|
| | 1449 | |
|---|
| | 1450 | ============================ =========================================== |
|---|
| | 1451 | Widget HTML Equivalent |
|---|
| | 1452 | ============================ =========================================== |
|---|
| | 1453 | ``TextInput`` ``<input type='text' ...`` |
|---|
| | 1454 | ``PasswordInput`` ``<input type='password' ...`` |
|---|
| | 1455 | ``HiddenInput`` ``<input type='hidden' ...`` |
|---|
| | 1456 | ``MultipleHiddenInput`` Multiple ``<input type='hidden' ...`` |
|---|
| | 1457 | instances. |
|---|
| | 1458 | ``FileInput`` ``<input type='file' ...`` |
|---|
| | 1459 | ``Textarea`` ``<textarea>...</textarea>`` |
|---|
| | 1460 | ``CheckboxInput`` ``<input type='checkbox' ...`` |
|---|
| | 1461 | ``Select`` ``<select><option ...`` |
|---|
| | 1462 | ``NullBooleanSelect`` Select widget with options 'Unknown', |
|---|
| | 1463 | 'Yes' and 'No' |
|---|
| | 1464 | ``SelectMultiple`` ``<select multiple='multiple'><option ...`` |
|---|
| | 1465 | ``RadioSelect`` ``<ul><li><input type='radio' ...`` |
|---|
| | 1466 | ``CheckboxSelectMultiple`` ``<ul><li><input type='checkbox' ...`` |
|---|
| | 1467 | ``MultiWidget`` Wrapper around multiple other widgets |
|---|
| | 1468 | ``SplitDateTimeWidget`` Wrapper around two ``TextInput`` widgets: |
|---|
| | 1469 | one for the Date, and one for the Time. |
|---|
| | 1470 | ============================ =========================================== |
|---|
| | 1471 | |
|---|
| | 1472 | Specifying widgets |
|---|
| | 1473 | ------------------ |
|---|
| | 1474 | |
|---|
| | 1475 | Whenever you specify a field on a form, Django will use a default widget |
|---|
| | 1476 | that is appropriate to the type of data that is to be displayed. To find |
|---|
| | 1477 | which widget is used on which field, see the documentation for the |
|---|
| | 1478 | built-in Field classes. |
|---|
| | 1479 | |
|---|
| | 1480 | However, if you want to use a different widget for a field, you can - |
|---|
| | 1481 | just use the 'widget' argument on the field definition. For example:: |
|---|
| | 1482 | |
|---|
| | 1483 | class CommentForm(forms.Form): |
|---|
| | 1484 | name = forms.CharField() |
|---|
| | 1485 | url = forms.URLField() |
|---|
| | 1486 | comment = forms.CharField(widget=forms.TextArea) |
|---|
| | 1487 | |
|---|
| | 1488 | This would specify a form with a comment that uses a larger TextArea widget, |
|---|
| | 1489 | rather than the default TextInput widget. |
|---|
| | 1490 | |
|---|
| | 1491 | Customizing widget instances |
|---|
| | 1492 | ---------------------------- |
|---|
| | 1493 | |
|---|
| | 1494 | When Django renders a widget as HTML, it only renders the bare minimum |
|---|
| | 1495 | HTML - Django doesn't add a class definition, or any other widget-specific |
|---|
| | 1496 | attributes. This means that all 'TextInput' widgets will appear the same |
|---|
| | 1497 | on your web page. |
|---|
| | 1498 | |
|---|
| | 1499 | If you want to make one widget look different to another, you need to |
|---|
| | 1500 | specify additional attributes for each widget. When you specify a |
|---|
| | 1501 | widget, you can provide a list of attributes that will be added to the |
|---|
| | 1502 | rendered HTML for the widget. |
|---|
| | 1503 | |
|---|
| | 1504 | For example, take the following simple form:: |
|---|
| | 1505 | |
|---|
| | 1506 | class CommentForm(forms.Form): |
|---|
| | 1507 | name = forms.CharField() |
|---|
| | 1508 | url = forms.URLField() |
|---|
| | 1509 | comment = forms.CharField() |
|---|
| | 1510 | |
|---|
| | 1511 | This form will include three default TextInput widgets, with default rendering - |
|---|
| | 1512 | no CSS class, no extra attributes. This means that the inputs boxes provided for |
|---|
| | 1513 | each widget will be rendered exactly the same:: |
|---|
| | 1514 | |
|---|
| | 1515 | >>> f = CommentForm(auto_id=False) |
|---|
| | 1516 | >>> f.as_table() |
|---|
| | 1517 | <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> |
|---|
| | 1518 | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
|---|
| | 1519 | <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr> |
|---|
| | 1520 | |
|---|
| | 1521 | On a real web page, you probably don't want every widget to look the same. You |
|---|
| | 1522 | might want a larger input element for the comment, and you might want the |
|---|
| | 1523 | 'name' widget to have some special CSS class. To do this, you specify a |
|---|
| | 1524 | custom widget for your fields, and specify some attributes to use |
|---|
| | 1525 | when rendering those widgets:: |
|---|
| | 1526 | |
|---|
| | 1527 | class CommentForm(forms.Form): |
|---|
| | 1528 | name = forms.CharField( |
|---|
| | 1529 | widget=forms.TextInput(attrs={'class':'special'})) |
|---|
| | 1530 | url = forms.URLField() |
|---|
| | 1531 | comment = forms.CharField( |
|---|
| | 1532 | widget=forms.TextInput(attrs={'size':'40'})) |
|---|
| | 1533 | |
|---|
| | 1534 | Django will then include the extra attributes in the rendered output:: |
|---|
| | 1535 | |
|---|
| | 1536 | >>> f = CommentForm(auto_id=False) |
|---|
| | 1537 | >>> f.as_table() |
|---|
| | 1538 | <tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr> |
|---|
| | 1539 | <tr><th>Url:</th><td><input type="text" name="url"/></td></tr> |
|---|
| | 1540 | <tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr> |
|---|
| | 1541 | |
|---|
| | 1542 | Custom Widgets |
|---|
| | 1543 | -------------- |
|---|
| | 1544 | |
|---|
| | 1545 | When you start to write a lot of forms, you will probably find that you will |
|---|
| | 1546 | reuse certain sets of widget attributes over and over again. Rather than |
|---|
| | 1547 | repeat these attribute definitions every time you need them, Django allows |
|---|
| | 1548 | you to capture those definitions as a custom widget. |
|---|
| | 1549 | |
|---|
| | 1550 | For example, if you find that you are including a lot of comment fields on forms, |
|---|
| | 1551 | you could capture the idea of a ``TextInput`` with a specific ``size`` attribute |
|---|
| | 1552 | as a custom extension to the ``TextInput`` widget:: |
|---|
| | 1553 | |
|---|
| | 1554 | class CommentWidget(forms.TextInput): |
|---|
| | 1555 | def __init__(self, *args, **kwargs): |
|---|
| | 1556 | kwargs.setdefault('attrs',{}).update({'size': '40'}) |
|---|
| | 1557 | super(forms.TextInput, self).__init__(*args, **kwargs) |
|---|
| | 1558 | |
|---|
| | 1559 | Then you can use this widget in your forms:: |
|---|
| | 1560 | |
|---|
| | 1561 | class CommentForm(forms.Form): |
|---|
| | 1562 | name = forms.CharField() |
|---|
| | 1563 | url = forms.URLField() |
|---|
| | 1564 | comment = forms.CharField(widget=CommentWidget) |
|---|
| | 1565 | |
|---|
| | 1566 | You can even customize your custom widget, in the same way as you would |
|---|
| | 1567 | any other widget. Adding a once-off class to your ``CommentWidget`` is as |
|---|
| | 1568 | simple as adding an attribute definition:: |
|---|
| | 1569 | |
|---|
| | 1570 | class CommentForm(forms.Form): |
|---|
| | 1571 | name = forms.CharField(max_length=20) |
|---|
| | 1572 | url = forms.URLField() |
|---|
| | 1573 | comment = forms.CharField( |
|---|
| | 1574 | widget=CommentWidget(attrs={'class': 'special'})) |
|---|
| | 1575 | |
|---|
| | 1576 | Django also makes it easy to specify a custom field type that uses your custom |
|---|
| | 1577 | widget. For example, you could define a customized field type for comments |
|---|
| | 1578 | by defining:: |
|---|
| | 1579 | |
|---|
| | 1580 | class CommentInput(forms.CharField): |
|---|
| | 1581 | widget = CommentWidget |
|---|
| | 1582 | |
|---|
| | 1583 | You can then use this field whenever you have a form that requires a comment:: |
|---|
| | 1584 | |
|---|
| | 1585 | class CommentForm(forms.Form): |
|---|
| | 1586 | name = forms.CharField() |
|---|
| | 1587 | url = forms.URLField() |
|---|
| | 1588 | comment = CommentInput() |
|---|
| | 1589 | |
|---|