Ticket #3512: html_class4.3.diff

File html_class4.3.diff, 111.7 KB (added by SmileyChris, 8 years ago)

add updated tests for modeltests.model_forms too

  • django/newforms/forms.py

     
    110110        """
    111111        return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name
    112112
    113     def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row):
     113    def _html_output(self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row, html_class_list=None):
    114114        "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
    115115        top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
    116116        output, hidden_fields = [], []
     117        html_class_list = html_class_list or []
    117118        for name, field in self.fields.items():
    118119            bf = BoundField(self, field, name)
    119120            bf_errors = ErrorList([escape(error) for error in bf.errors]) # Escape and cache in local variable.
     
    122123                    top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors])
    123124                hidden_fields.append(unicode(bf))
    124125            else:
     126                class_list = list(html_class_list) # A fresh list for each loop.
     127                if bf_errors:
     128                    class_list.append('error')
     129                if bf.field.required:
     130                    class_list.append('required')
     131                if class_list:
     132                    html_class = ' class="%s"' % ' '.join(class_list)
     133                else:
     134                    html_class = ''
    125135                if errors_on_separate_row and bf_errors:
    126136                    output.append(error_row % bf_errors)
    127137                if bf.label:
     
    136146                    help_text = help_text_html % field.help_text
    137147                else:
    138148                    help_text = u''
    139                 output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': unicode(bf), 'help_text': help_text})
     149                output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': unicode(bf), 'help_text': help_text, 'html_class': html_class})
    140150        if top_errors:
    141151            output.insert(0, error_row % top_errors)
    142152        if hidden_fields: # Insert any hidden fields in the last row.
     
    151161
    152162    def as_table(self):
    153163        "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
    154         return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
     164        return self._html_output(u'<tr%(html_class)s><th>%(label)s</th><td>%(errors)s%(field)s%(help_text)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', u'<br />%s', False)
    155165
    156166    def as_ul(self):
    157167        "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
    158         return self._html_output(u'<li>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False)
     168        return self._html_output(u'<li%(html_class)s>%(errors)s%(label)s %(field)s%(help_text)s</li>', u'<li>%s</li>', '</li>', u' %s', False)
    159169
    160170    def as_p(self):
    161171        "Returns this form rendered as HTML <p>s."
    162         return self._html_output(u'<p>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True)
     172        return self._html_output(u'<p%(html_class)s>%(label)s %(field)s%(help_text)s</p>', u'<p>%s</p>', '</p>', u' %s', True)
    163173
    164174    def non_field_errors(self):
    165175        """
  • docs/newforms.txt

     
    328328
    329329    >>> f = ContactForm()
    330330    >>> print f
    331     <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
    332     <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
    333     <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
    334     <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
     331    <tr class="required"><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
     332    <tr class="required"><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
     333    <tr class="required"><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
     334    <tr class="required"><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
    335335
    336336If the form is bound to data, the HTML output will include that data
    337337appropriately. For example, if a field is represented by an
     
    345345    ...         'cc_myself': True}
    346346    >>> f = ContactForm(data)
    347347    >>> print f
    348     <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
    349     <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
    350     <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
    351     <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>
     348    <tr class="required"><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
     349    <tr class="required"><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
     350    <tr class="required"><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
     351    <tr class="required"><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>
    352352
    353353This default output is a two-column HTML table, with a ``<tr>`` for each field.
    354354Notice the following:
     
    389389
    390390    >>> f = ContactForm()
    391391    >>> f.as_p()
    392     u'<p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
     392    u'<p class="required"><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>\n<p class="required"><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>\n<p class="required"><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>\n<p class="required"><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>'
    393393    >>> print f.as_p()
    394     <p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
    395     <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
    396     <p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>
    397     <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
     394    <p class="required"><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
     395    <p class="required"><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
     396    <p class="required"><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>
     397    <p class="required"><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>
    398398
    399399``as_ul()``
    400400~~~~~~~~~~~
     
    405405
    406406    >>> f = ContactForm()
    407407    >>> f.as_ul()
    408     u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
     408    u'<li class="required"><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li class="required"><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li class="required"><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li class="required"><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
    409409    >>> print f.as_ul()
    410     <li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>
    411     <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
    412     <li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>
    413     <li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>
     410    <li class="required"><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>
     411    <li class="required"><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
     412    <li class="required"><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>
     413    <li class="required"><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>
    414414
    415415``as_table()``
    416416~~~~~~~~~~~~~~
     
    421421
    422422    >>> f = ContactForm()
    423423    >>> f.as_table()
    424     u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
     424    u'<tr class="required"><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr class="required"><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr class="required"><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr class="required"><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
    425425    >>> print f.as_table()
    426     <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
    427     <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
    428     <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
    429     <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
     426    <tr class="required"><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
     427    <tr class="required"><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
     428    <tr class="required"><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
     429    <tr class="required"><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>
    430430
    431431Configuring HTML ``<label>`` tags
    432432~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     
    449449
    450450    >>> f = ContactForm(auto_id=False)
    451451    >>> print f.as_table()
    452     <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
    453     <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
    454     <tr><th>Sender:</th><td><input type="text" name="sender" /></td></tr>
    455     <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
     452    <tr class="required"><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
     453    <tr class="required"><th>Message:</th><td><input type="text" name="message" /></td></tr>
     454    <tr class="required"><th>Sender:</th><td><input type="text" name="sender" /></td></tr>
     455    <tr class="required"><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
    456456    >>> print f.as_ul()
    457     <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
    458     <li>Message: <input type="text" name="message" /></li>
    459     <li>Sender: <input type="text" name="sender" /></li>
    460     <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
     457    <li class="required">Subject: <input type="text" name="subject" maxlength="100" /></li>
     458    <li class="required">Message: <input type="text" name="message" /></li>
     459    <li class="required">Sender: <input type="text" name="sender" /></li>
     460    <li class="required">Cc myself: <input type="checkbox" name="cc_myself" /></li>
    461461    >>> print f.as_p()
    462     <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
    463     <p>Message: <input type="text" name="message" /></p>
    464     <p>Sender: <input type="text" name="sender" /></p>
    465     <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
     462    <p class="required">Subject: <input type="text" name="subject" maxlength="100" /></p>
     463    <p class="required">Message: <input type="text" name="message" /></p>
     464    <p class="required">Sender: <input type="text" name="sender" /></p>
     465    <p class="required">Cc myself: <input type="checkbox" name="cc_myself" /></p>
    466466
    467467If ``auto_id`` is set to ``True``, then the form output *will* include
    468468``<label>`` tags and will simply use the field name as its ``id`` for each form
     
    470470
    471471    >>> f = ContactForm(auto_id=True)
    472472    >>> print f.as_table()
    473     <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
    474     <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
    475     <tr><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr>
    476     <tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
     473    <tr class="required"><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
     474    <tr class="required"><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
     475    <tr class="required"><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr>
     476    <tr class="required"><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
    477477    >>> print f.as_ul()
    478     <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
    479     <li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
    480     <li><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li>
    481     <li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
     478    <li class="required"><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
     479    <li class="required"><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
     480    <li class="required"><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li>
     481    <li class="required"><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
    482482    >>> print f.as_p()
    483     <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
    484     <p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
    485     <p><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p>
    486     <p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>
     483    <p class="required"><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
     484    <p class="required"><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
     485    <p class="required"><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p>
     486    <p class="required"><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>
    487487
    488488If ``auto_id`` is set to a string containing the format character ``'%s'``,
    489489then the form output will include ``<label>`` tags, and will generate ``id``
     
    493493
    494494    >>> f = ContactForm(auto_id='id_for_%s')
    495495    >>> print f.as_table()
    496     <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
    497     <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
    498     <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr>
    499     <tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
     496    <tr class="required"><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
     497    <tr class="required"><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
     498    <tr class="required"><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr>
     499    <tr class="required"><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
    500500    >>> print f.as_ul()
    501     <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
    502     <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
    503     <li><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li>
    504     <li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
     501    <li class="required"><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
     502    <li class="required"><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
     503    <li class="required"><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li>
     504    <li class="required"><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
    505505    >>> print f.as_p()
    506     <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
    507     <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
    508     <p><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p>
    509     <p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>
     506    <p class="required"><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
     507    <p class="required"><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
     508    <p class="required"><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p>
     509    <p class="required"><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>
    510510
    511511If ``auto_id`` is set to any other true value -- such as a string that doesn't
    512512include ``%s`` -- then the library will act as if ``auto_id`` is ``True``.
     
    537537    ...         'cc_myself': True}
    538538    >>> f = ContactForm(data, auto_id=False)
    539539    >>> print f.as_table()
    540     <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
    541     <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
    542     <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr>
    543     <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
     540    <tr class="error required"><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
     541    <tr class="required"><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
     542    <tr class="error required"><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul><input type="text" name="sender" value="invalid e-mail address" /></td></tr>
     543    <tr class="required"><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
    544544    >>> print f.as_ul()
    545     <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
    546     <li>Message: <input type="text" name="message" value="Hi there" /></li>
    547     <li><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li>
    548     <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
     545    <li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
     546    <li class="required">Message: <input type="text" name="message" value="Hi there" /></li>
     547    <li class="error required"><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul>Sender: <input type="text" name="sender" value="invalid e-mail address" /></li>
     548    <li class="required">Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
    549549    >>> print f.as_p()
    550550    <p><ul class="errorlist"><li>This field is required.</li></ul></p>
    551     <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
    552     <p>Message: <input type="text" name="message" value="Hi there" /></p>
     551    <p class="error required">Subject: <input type="text" name="subject" maxlength="100" /></p>
     552    <p class="required">Message: <input type="text" name="message" value="Hi there" /></p>
    553553    <p><ul class="errorlist"><li>Enter a valid e-mail address.</li></ul></p>
    554     <p>Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
    555     <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
     554    <p class="error required">Sender: <input type="text" name="sender" value="invalid e-mail address" /></p>
     555    <p class="required">Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>
    556556
     557You will notice that each row which is required is given the HTML class name
     558``required`` and any row which the field did not pass validation receives the
     559``error`` class name.
     560
    557561More granular output
    558562~~~~~~~~~~~~~~~~~~~~
    559563
     
    728732    ...     priority = forms.CharField()
    729733    >>> f = ContactFormWithPriority(auto_id=False)
    730734    >>> print f.as_ul()
    731     <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
    732     <li>Message: <input type="text" name="message" /></li>
    733     <li>Sender: <input type="text" name="sender" /></li>
    734     <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
    735     <li>Priority: <input type="text" name="priority" /></li>
     735    <li class="required">Subject: <input type="text" name="subject" maxlength="100" /></li>
     736    <li class="required">Message: <input type="text" name="message" /></li>
     737    <li class="required">Sender: <input type="text" name="sender" /></li>
     738    <li class="required">Cc myself: <input type="checkbox" name="cc_myself" /></li>
     739    <li class="required">Priority: <input type="text" name="priority" /></li>
    736740
    737741It's possible to subclass multiple forms, treating forms as "mix-ins." In this
    738742example, ``BeatleForm`` subclasses both ``PersonForm`` and ``InstrumentForm``
     
    748752    ...     haircut_type = CharField()
    749753    >>> b = BeatleForm(auto_id=False)
    750754    >>> print b.as_ul()
    751     <li>First name: <input type="text" name="first_name" /></li>
    752     <li>Last name: <input type="text" name="last_name" /></li>
    753     <li>Instrument: <input type="text" name="instrument" /></li>
    754     <li>Haircut type: <input type="text" name="haircut_type" /></li>
     755    <li class="required">First name: <input type="text" name="first_name" /></li>
     756    <li class="required">Last name: <input type="text" name="last_name" /></li>
     757    <li class="required">Instrument: <input type="text" name="instrument" /></li>
     758    <li class="required">Haircut type: <input type="text" name="haircut_type" /></li>
    755759
    756760Fields
    757761======
     
    858862    ...     comment = forms.CharField()
    859863    >>> f = CommentForm(auto_id=False)
    860864    >>> print f
    861     <tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
     865    <tr class="required"><th>Your name:</th><td><input type="text" name="name" /></td></tr>
    862866    <tr><th>Your Web site:</th><td><input type="text" name="url" /></td></tr>
    863     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
     867    <tr class="required"><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
    864868
    865869``initial``
    866870~~~~~~~~~~~
     
    877881    ...     comment = forms.CharField()
    878882    >>> f = CommentForm(auto_id=False)
    879883    >>> print f
    880     <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
    881     <tr><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr>
    882     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
     884    <tr class="required"><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
     885    <tr class="required"><th>Url:</th><td><input type="text" name="url" value="http://" /></td></tr>
     886    <tr class="required"><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
    883887
    884888You may be thinking, why not just pass a dictionary of the initial values as
    885889data when displaying the form? Well, if you do that, you'll trigger validation,
     
    892896    >>> default_data = {'name': 'Your name', 'url': 'http://'}
    893897    >>> f = CommentForm(default_data, auto_id=False)
    894898    >>> print f
    895     <tr><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
    896     <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr>
    897     <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
     899    <tr class="required"><th>Name:</th><td><input type="text" name="name" value="Your name" /></td></tr>
     900    <tr class="required"><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="text" name="url" value="http://" /></td></tr>
     901    <tr class="required"><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" /></td></tr>
    898902
    899903This is why ``initial`` values are only displayed for unbound forms. For bound
    900904forms, the HTML output will use the bound data.
     
    939943    ...     cc_myself = forms.BooleanField()
    940944    >>> f = HelpTextContactForm(auto_id=False)
    941945    >>> print f.as_table()
    942     <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr>
    943     <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
    944     <tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr>
    945     <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
     946    <tr class="required"><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br />100 characters max.</td></tr>
     947    <tr class="required"><th>Message:</th><td><input type="text" name="message" /></td></tr>
     948    <tr class="required"><th>Sender:</th><td><input type="text" name="sender" /><br />A valid e-mail address, please.</td></tr>
     949    <tr class="required"><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
    946950    >>> print f.as_ul()
    947     <li>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li>
    948     <li>Message: <input type="text" name="message" /></li>
    949     <li>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li>
    950     <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
     951    <li class="required">Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</li>
     952    <li class="required">Message: <input type="text" name="message" /></li>
     953    <li class="required">Sender: <input type="text" name="sender" /> A valid e-mail address, please.</li>
     954    <li class="required">Cc myself: <input type="checkbox" name="cc_myself" /></li>
    951955    >>> print f.as_p()
    952     <p>Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p>
    953     <p>Message: <input type="text" name="message" /></p>
    954     <p>Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p>
    955     <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
     956    <p class="required">Subject: <input type="text" name="subject" maxlength="100" /> 100 characters max.</p>
     957    <p class="required">Message: <input type="text" name="message" /></p>
     958    <p class="required">Sender: <input type="text" name="sender" /> A valid e-mail address, please.</p>
     959    <p class="required">Cc myself: <input type="checkbox" name="cc_myself" /></p>
    956960
    957961Dynamic initial values
    958962----------------------
     
    973977    ...     comment = forms.CharField()
    974978    >>> f = CommentForm(initial={'name': 'your username'}, auto_id=False)
    975979    >>> print f
    976     <tr><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr>
    977     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
    978     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
     980    <tr class="required"><th>Name:</th><td><input type="text" name="name" value="your username" /></td></tr>
     981    <tr class="required"><th>Url:</th><td><input type="text" name="url" /></td></tr>
     982    <tr class="required"><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
    979983    >>> f = CommentForm(initial={'name': 'another username'}, auto_id=False)
    980984    >>> print f
    981     <tr><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr>
    982     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
    983     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
     985    <tr class="required"><th>Name:</th><td><input type="text" name="name" value="another username" /></td></tr>
     986    <tr class="required"><th>Url:</th><td><input type="text" name="url" /></td></tr>
     987    <tr class="required"><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
    984988
    985989Just like the ``initial`` parameter to ``Field``, these values are only
    986990displayed for unbound forms, and they're not used as fallback values if a
     
    9971001    ...     comment = forms.CharField()
    9981002    >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
    9991003    >>> print f
    1000     <tr><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
    1001     <tr><th>Url:</th><td><input type="text" name="url" /></td></tr>
    1002     <tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
     1004    <tr class="required"><th>Name:</th><td><input type="text" name="name" value="instance" /></td></tr>
     1005    <tr class="required"><th>Url:</th><td><input type="text" name="url" /></td></tr>
     1006    <tr class="required"><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
    10031007
    10041008Built-in ``Field`` classes
    10051009--------------------------
  • tests/modeltests/model_forms/models.py

     
    7878>>> CategoryForm = form_for_model(Category)
    7979>>> f = CategoryForm()
    8080>>> print f
    81 <tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
    82 <tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
     81<tr class="required"><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
     82<tr class="required"><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
    8383>>> print f.as_ul()
    84 <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
    85 <li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>
     84<li class="required"><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
     85<li class="required"><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>
    8686>>> print f['name']
    8787<input id="id_name" type="text" name="name" maxlength="20" />
    8888
    8989>>> f = CategoryForm(auto_id=False)
    9090>>> print f.as_ul()
    91 <li>Name: <input type="text" name="name" maxlength="20" /></li>
    92 <li>The URL: <input type="text" name="url" maxlength="40" /></li>
     91<li class="required">Name: <input type="text" name="name" maxlength="20" /></li>
     92<li class="required">The URL: <input type="text" name="url" maxlength="40" /></li>
    9393
    9494>>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'})
    9595>>> f.is_valid()
     
    159159>>> ArticleForm = form_for_model(Article)
    160160>>> f = ArticleForm(auto_id=False)
    161161>>> print f
    162 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
    163 <tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
    164 <tr><th>Writer:</th><td><select name="writer">
     162<tr class="required"><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
     163<tr class="required"><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
     164<tr class="required"><th>Writer:</th><td><select name="writer">
    165165<option value="" selected="selected">---------</option>
    166166<option value="1">Mike Royko</option>
    167167<option value="2">Bob Woodward</option>
    168168</select></td></tr>
    169 <tr><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
     169<tr class="required"><th>Article:</th><td><textarea rows="10" cols="40" name="article"></textarea></td></tr>
    170170<tr><th>Status:</th><td><select name="status">
    171171<option value="" selected="selected">---------</option>
    172172<option value="1">Draft</option>
     
    188188>>> PartialArticleForm = form_for_model(Article, fields=('headline','pub_date'))
    189189>>> f = PartialArticleForm(auto_id=False)
    190190>>> print f
    191 <tr><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
    192 <tr><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
     191<tr class="required"><th>Headline:</th><td><input type="text" name="headline" maxlength="50" /></td></tr>
     192<tr class="required"><th>Pub date:</th><td><input type="text" name="pub_date" /></td></tr>
    193193
    194194You can pass a custom Form class to form_for_model. Make sure it's a
    195195subclass of BaseForm, not Form.
     
    208208>>> RoykoForm = form_for_instance(w)
    209209>>> f = RoykoForm(auto_id=False)
    210210>>> print f
    211 <tr><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
     211<tr class="required"><th>Name:</th><td><input type="text" name="name" value="Mike Royko" maxlength="50" /><br />Use both first and last names.</td></tr>
    212212
    213213>>> art = Article(headline='Test article', pub_date=datetime.date(1988, 1, 4), writer=w, article='Hello.')
    214214>>> art.save()
     
    217217>>> TestArticleForm = form_for_instance(art)
    218218>>> f = TestArticleForm(auto_id=False)
    219219>>> print f.as_ul()
    220 <li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
    221 <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
    222 <li>Writer: <select name="writer">
     220<li class="required">Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
     221<li class="required">Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     222<li class="required">Writer: <select name="writer">
    223223<option value="">---------</option>
    224224<option value="1" selected="selected">Mike Royko</option>
    225225<option value="2">Bob Woodward</option>
    226226</select></li>
    227 <li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
     227<li class="required">Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
    228228<li>Status: <select name="status">
    229229<option value="" selected="selected">---------</option>
    230230<option value="1">Draft</option>
     
    251251>>> PartialArticleForm = form_for_instance(art, fields=('headline','pub_date'))
    252252>>> f = PartialArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04'}, auto_id=False)
    253253>>> print f.as_ul()
    254 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
    255 <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     254<li class="required">Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
     255<li class="required">Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
    256256>>> f.is_valid()
    257257True
    258258>>> new_art = f.save()
     
    271271>>> TestArticleForm = form_for_instance(new_art)
    272272>>> f = TestArticleForm(auto_id=False)
    273273>>> print f.as_ul()
    274 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
    275 <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
    276 <li>Writer: <select name="writer">
     274<li class="required">Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
     275<li class="required">Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     276<li class="required">Writer: <select name="writer">
    277277<option value="">---------</option>
    278278<option value="1" selected="selected">Mike Royko</option>
    279279<option value="2">Bob Woodward</option>
    280280</select></li>
    281 <li>Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
     281<li class="required">Article: <textarea rows="10" cols="40" name="article">Hello.</textarea></li>
    282282<li>Status: <select name="status">
    283283<option value="" selected="selected">---------</option>
    284284<option value="1">Draft</option>
     
    355355>>> ArticleForm = form_for_model(Article)
    356356>>> f = ArticleForm(auto_id=False)
    357357>>> print f.as_ul()
    358 <li>Headline: <input type="text" name="headline" maxlength="50" /></li>
    359 <li>Pub date: <input type="text" name="pub_date" /></li>
    360 <li>Writer: <select name="writer">
     358<li class="required">Headline: <input type="text" name="headline" maxlength="50" /></li>
     359<li class="required">Pub date: <input type="text" name="pub_date" /></li>
     360<li class="required">Writer: <select name="writer">
    361361<option value="" selected="selected">---------</option>
    362362<option value="1">Mike Royko</option>
    363363<option value="2">Bob Woodward</option>
    364364</select></li>
    365 <li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
     365<li class="required">Article: <textarea rows="10" cols="40" name="article"></textarea></li>
    366366<li>Status: <select name="status">
    367367<option value="" selected="selected">---------</option>
    368368<option value="1">Draft</option>
     
    379379>>> Writer.objects.create(name='Carl Bernstein')
    380380<Writer: Carl Bernstein>
    381381>>> print f.as_ul()
    382 <li>Headline: <input type="text" name="headline" maxlength="50" /></li>
    383 <li>Pub date: <input type="text" name="pub_date" /></li>
    384 <li>Writer: <select name="writer">
     382<li class="required">Headline: <input type="text" name="headline" maxlength="50" /></li>
     383<li class="required">Pub date: <input type="text" name="pub_date" /></li>
     384<li class="required">Writer: <select name="writer">
    385385<option value="" selected="selected">---------</option>
    386386<option value="1">Mike Royko</option>
    387387<option value="2">Bob Woodward</option>
    388388<option value="3">Carl Bernstein</option>
    389389</select></li>
    390 <li>Article: <textarea rows="10" cols="40" name="article"></textarea></li>
     390<li class="required">Article: <textarea rows="10" cols="40" name="article"></textarea></li>
    391391<li>Status: <select name="status">
    392392<option value="" selected="selected">---------</option>
    393393<option value="1">Draft</option>
  • tests/regressiontests/forms/regressions.py

     
    99...     f1 = CharField(max_length=10, widget=TextInput(attrs=extra_attrs))
    1010...     f2 = CharField(widget=TextInput(attrs=extra_attrs))
    1111>>> TestForm(auto_id=False).as_p()
    12 u'<p>F1: <input type="text" class="special" name="f1" maxlength="10" /></p>\n<p>F2: <input type="text" class="special" name="f2" /></p>'
     12u'<p class="required">F1: <input type="text" class="special" name="f1" maxlength="10" /></p>\n<p class="required">F2: <input type="text" class="special" name="f2" /></p>'
    1313
    1414#######################
    1515# Tests for form i18n #
     
    2121...     username = CharField(max_length=10, label=gettext_lazy('Username'))
    2222>>> f = SomeForm()
    2323>>> print f.as_p()
    24 <p><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
     24<p class="required"><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
    2525>>> activate('de')
    2626>>> print f.as_p()
    27 <p><label for="id_username">Benutzername:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
     27<p class="required"><label for="id_username">Benutzername:</label> <input id="id_username" type="text" name="username" maxlength="10" /></p>
    2828>>> deactivate()
    2929
    3030Unicode decoding problems...
     
    3333...     somechoice = ChoiceField(choices=GENDERS, widget=RadioSelect())
    3434>>> f = SomeForm()
    3535>>> f.as_p()
    36 u'<p><label for="id_somechoice_0">Somechoice:</label> <ul>\n<li><label><input type="radio" id="id_somechoice_0" value="0" name="somechoice" /> En tied\xe4</label></li>\n<li><label><input type="radio" id="id_somechoice_1" value="1" name="somechoice" /> Mies</label></li>\n<li><label><input type="radio" id="id_somechoice_2" value="2" name="somechoice" /> Nainen</label></li>\n</ul></p>'
     36u'<p class="required"><label for="id_somechoice_0">Somechoice:</label> <ul>\n<li><label><input type="radio" id="id_somechoice_0" value="0" name="somechoice" /> En tied\xe4</label></li>\n<li><label><input type="radio" id="id_somechoice_1" value="1" name="somechoice" /> Mies</label></li>\n<li><label><input type="radio" id="id_somechoice_2" value="2" name="somechoice" /> Nainen</label></li>\n</ul></p>'
    3737
    3838#######################
    3939# Miscellaneous Tests #
  • tests/regressiontests/forms/tests.py

     
    343343...     somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things]))
    344344>>> f = SomeForm()
    345345>>> f.as_table()
    346 u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
     346u'<tr class="required"><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
    347347>>> f.as_table()
    348 u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
     348u'<tr class="required"><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
    349349>>> f = SomeForm({'somechoice': 2})
    350350>>> f.as_table()
    351 u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>'
     351u'<tr class="required"><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>'
    352352
    353353You can also pass 'choices' to the constructor:
    354354>>> w = Select(choices=[(1, 1), (2, 2), (3, 3)])
     
    19291929Last name Lennon
    19301930Birthday 1940-10-9
    19311931>>> print p
    1932 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
    1933 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr>
    1934 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>
     1932<tr class="required"><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
     1933<tr class="required"><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr>
     1934<tr class="required"><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>
    19351935
    19361936Empty dictionaries are valid, too.
    19371937>>> p = Person({})
     
    19461946...
    19471947AttributeError: 'Person' object has no attribute 'cleaned_data'
    19481948>>> print p
    1949 <tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
    1950 <tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
    1951 <tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
     1949<tr class="error required"><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
     1950<tr class="error required"><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
     1951<tr class="error required"><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
    19521952>>> print p.as_table()
    1953 <tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
    1954 <tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
    1955 <tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
     1953<tr class="error required"><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
     1954<tr class="error required"><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
     1955<tr class="error required"><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
    19561956>>> print p.as_ul()
    1957 <li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
    1958 <li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
    1959 <li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
     1957<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
     1958<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
     1959<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
    19601960>>> print p.as_p()
    19611961<p><ul class="errorlist"><li>This field is required.</li></ul></p>
    1962 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
     1962<p class="error required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
    19631963<p><ul class="errorlist"><li>This field is required.</li></ul></p>
    1964 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
     1964<p class="error required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
    19651965<p><ul class="errorlist"><li>This field is required.</li></ul></p>
    1966 <p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
     1966<p class="error required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
    19671967
    19681968If you don't pass any values to the Form's __init__(), or if you pass None,
    19691969the Form will be considered unbound and won't do any validation. Form.errors
     
    19801980...
    19811981AttributeError: 'Person' object has no attribute 'cleaned_data'
    19821982>>> print p
    1983 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
    1984 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
    1985 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
     1983<tr class="required"><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
     1984<tr class="required"><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
     1985<tr class="required"><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
    19861986>>> print p.as_table()
    1987 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
    1988 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
    1989 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
     1987<tr class="required"><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
     1988<tr class="required"><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
     1989<tr class="required"><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
    19901990>>> print p.as_ul()
    1991 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
    1992 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
    1993 <li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
     1991<li class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
     1992<li class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
     1993<li class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
    19941994>>> print p.as_p()
    1995 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
    1996 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
    1997 <p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
     1995<p class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
     1996<p class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
     1997<p class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
    19981998
    19991999Unicode values are handled properly.
    20002000>>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'})
    20012001>>> p.as_table()
    2002 u'<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></td></tr>\n<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>'
     2002u'<tr class="required"><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n<tr class="required"><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></td></tr>\n<tr class="required"><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>'
    20032003>>> p.as_ul()
    2004 u'<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></li>\n<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>'
     2004u'<li class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></li>\n<li class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n<li class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>'
    20052005>>> p.as_p()
    2006 u'<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></p>\n<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>'
     2006u'<p class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></p>\n<p class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n<p class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>'
    20072007
    20082008>>> p = Person({'last_name': u'Lennon'})
    20092009>>> p.errors
     
    20812081the human-readable labels for a field.
    20822082>>> p = Person(auto_id='%s_id')
    20832083>>> print p.as_table()
    2084 <tr><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr>
    2085 <tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr>
    2086 <tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr>
     2084<tr class="required"><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr>
     2085<tr class="required"><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr>
     2086<tr class="required"><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr>
    20872087>>> print p.as_ul()
    2088 <li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li>
    2089 <li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li>
    2090 <li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li>
     2088<li class="required"><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li>
     2089<li class="required"><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li>
     2090<li class="required"><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li>
    20912091>>> print p.as_p()
    2092 <p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p>
    2093 <p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p>
    2094 <p><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p>
     2092<p class="required"><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p>
     2093<p class="required"><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p>
     2094<p class="required"><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p>
    20952095
    20962096If auto_id is any True value whose str() does not contain '%s', the "id"
    20972097attribute will be the name of the field.
    20982098>>> p = Person(auto_id=True)
    20992099>>> print p.as_ul()
    2100 <li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li>
    2101 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
    2102 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
     2100<li class="required"><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li>
     2101<li class="required"><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
     2102<li class="required"><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
    21032103
    21042104If auto_id is any False value, an "id" attribute won't be output unless it
    21052105was manually entered.
    21062106>>> p = Person(auto_id=False)
    21072107>>> print p.as_ul()
    2108 <li>First name: <input type="text" name="first_name" /></li>
    2109 <li>Last name: <input type="text" name="last_name" /></li>
    2110 <li>Birthday: <input type="text" name="birthday" /></li>
     2108<li class="required">First name: <input type="text" name="first_name" /></li>
     2109<li class="required">Last name: <input type="text" name="last_name" /></li>
     2110<li class="required">Birthday: <input type="text" name="birthday" /></li>
    21112111
    21122112In this example, auto_id is False, but the "id" attribute for the "first_name"
    21132113field is given. Also note that field gets a <label>, while the others don't.
     
    21172117...     birthday = DateField()
    21182118>>> p = PersonNew(auto_id=False)
    21192119>>> print p.as_ul()
    2120 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
    2121 <li>Last name: <input type="text" name="last_name" /></li>
    2122 <li>Birthday: <input type="text" name="birthday" /></li>
     2120<li class="required"><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
     2121<li class="required">Last name: <input type="text" name="last_name" /></li>
     2122<li class="required">Birthday: <input type="text" name="birthday" /></li>
    21232123
    21242124If the "id" attribute is specified in the Form and auto_id is True, the "id"
    21252125attribute in the Form gets precedence.
    21262126>>> p = PersonNew(auto_id=True)
    21272127>>> print p.as_ul()
    2128 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
    2129 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
    2130 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
     2128<li class="required"><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
     2129<li class="required"><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
     2130<li class="required"><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
    21312131
    21322132>>> class SignupForm(Form):
    21332133...     email = EmailField()
     
    22752275<li><label><input type="radio" name="language" value="J" /> Java</label></li>
    22762276</ul>
    22772277>>> print f
    2278 <tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
    2279 <tr><th>Language:</th><td><ul>
     2278<tr class="required"><th>Name:</th><td><input type="text" name="name" /></td></tr>
     2279<tr class="required"><th>Language:</th><td><ul>
    22802280<li><label><input type="radio" name="language" value="P" /> Python</label></li>
    22812281<li><label><input type="radio" name="language" value="J" /> Java</label></li>
    22822282</ul></td></tr>
    22832283>>> print f.as_ul()
    2284 <li>Name: <input type="text" name="name" /></li>
    2285 <li>Language: <ul>
     2284<li class="required">Name: <input type="text" name="name" /></li>
     2285<li class="required">Language: <ul>
    22862286<li><label><input type="radio" name="language" value="P" /> Python</label></li>
    22872287<li><label><input type="radio" name="language" value="J" /> Java</label></li>
    22882288</ul></li>
     
    23012301either as_table() or as_ul(), the label for the RadioSelect will point to the
    23022302ID of the *first* radio button.
    23032303>>> print f
    2304 <tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr>
    2305 <tr><th><label for="id_language_0">Language:</label></th><td><ul>
     2304<tr class="required"><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr>
     2305<tr class="required"><th><label for="id_language_0">Language:</label></th><td><ul>
    23062306<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
    23072307<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
    23082308</ul></td></tr>
    23092309>>> print f.as_ul()
    2310 <li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
    2311 <li><label for="id_language_0">Language:</label> <ul>
     2310<li class="required"><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
     2311<li class="required"><label for="id_language_0">Language:</label> <ul>
    23122312<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
    23132313<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
    23142314</ul></li>
    23152315>>> print f.as_p()
    2316 <p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p>
    2317 <p><label for="id_language_0">Language:</label> <ul>
     2316<p class="required"><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p>
     2317<p class="required"><label for="id_language_0">Language:</label> <ul>
    23182318<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
    23192319<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
    23202320</ul></p>
     
    24122412...     composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=MultipleHiddenInput)
    24132413>>> f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False)
    24142414>>> print f.as_ul()
    2415 <li>Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" />
     2415<li class="required">Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" />
    24162416<input type="hidden" name="composers" value="P" /></li>
    24172417
    24182418When using CheckboxSelectMultiple, the framework expects a list of input and
     
    24392439
    24402440>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
    24412441>>> print f
    2442 <tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr>
     2442<tr class="error required"><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr>
    24432443>>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False)
    24442444>>> print f
    2445 <tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul><input type="text" name="special_name" value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" /></td></tr>
     2445<tr class="error required"><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul><input type="text" name="special_name" value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" /></td></tr>
    24462446
    24472447# Validating multiple fields in relation to another ###########################
    24482448
     
    24962496{}
    24972497>>> f = UserRegistration({}, auto_id=False)
    24982498>>> print f.as_table()
    2499 <tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr>
    2500 <tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr>
    2501 <tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr>
     2499<tr class="error required"><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr>
     2500<tr class="error required"><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr>
     2501<tr class="error required"><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr>
    25022502>>> f.errors
    25032503{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']}
    25042504>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)
     
    25062506{'__all__': [u'Please make sure your passwords match.']}
    25072507>>> print f.as_table()
    25082508<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr>
    2509 <tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>
    2510 <tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
    2511 <tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
     2509<tr class="required"><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>
     2510<tr class="required"><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
     2511<tr class="required"><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
    25122512>>> print f.as_ul()
    25132513<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li>
    2514 <li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>
    2515 <li>Password1: <input type="password" name="password1" value="foo" /></li>
    2516 <li>Password2: <input type="password" name="password2" value="bar" /></li>
     2514<li class="required">Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>
     2515<li class="required">Password1: <input type="password" name="password1" value="foo" /></li>
     2516<li class="required">Password2: <input type="password" name="password2" value="bar" /></li>
    25172517>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
    25182518>>> f.errors
    25192519{}
     
    25332533...         self.fields['birthday'] = DateField()
    25342534>>> p = Person(auto_id=False)
    25352535>>> print p
    2536 <tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
    2537 <tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
    2538 <tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr>
     2536<tr class="required"><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
     2537<tr class="required"><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
     2538<tr class="required"><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr>
    25392539
    25402540Instances of a dynamic Form do not persist fields from one Form instance to
    25412541the next.
     
    25472547>>> field_list = [('field1', CharField()), ('field2', CharField())]
    25482548>>> my_form = MyForm(field_list=field_list)
    25492549>>> print my_form
    2550 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
    2551 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
     2550<tr class="required"><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
     2551<tr class="required"><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
    25522552>>> field_list = [('field3', CharField()), ('field4', CharField())]
    25532553>>> my_form = MyForm(field_list=field_list)
    25542554>>> print my_form
    2555 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
    2556 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
     2555<tr class="required"><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
     2556<tr class="required"><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
    25572557
    25582558>>> class MyForm(Form):
    25592559...     default_field_1 = CharField()
     
    25652565>>> field_list = [('field1', CharField()), ('field2', CharField())]
    25662566>>> my_form = MyForm(field_list=field_list)
    25672567>>> print my_form
    2568 <tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
    2569 <tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
    2570 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
    2571 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
     2568<tr class="required"><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
     2569<tr class="required"><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
     2570<tr class="required"><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
     2571<tr class="required"><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
    25722572>>> field_list = [('field3', CharField()), ('field4', CharField())]
    25732573>>> my_form = MyForm(field_list=field_list)
    25742574>>> print my_form
    2575 <tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
    2576 <tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
    2577 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
    2578 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
     2575<tr class="required"><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
     2576<tr class="required"><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
     2577<tr class="required"><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
     2578<tr class="required"><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
    25792579
    25802580Similarly, changes to field attributes do not persist from one Form instance
    25812581to the next.
     
    26252625...     birthday = DateField()
    26262626>>> p = Person(auto_id=False)
    26272627>>> print p
    2628 <tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
    2629 <tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
    2630 <tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr>
     2628<tr class="required"><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
     2629<tr class="required"><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
     2630<tr class="required"><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr>
    26312631>>> print p.as_ul()
    2632 <li>First name: <input type="text" name="first_name" /></li>
    2633 <li>Last name: <input type="text" name="last_name" /></li>
    2634 <li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li>
     2632<li class="required">First name: <input type="text" name="first_name" /></li>
     2633<li class="required">Last name: <input type="text" name="last_name" /></li>
     2634<li class="required">Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li>
    26352635>>> print p.as_p()
    2636 <p>First name: <input type="text" name="first_name" /></p>
    2637 <p>Last name: <input type="text" name="last_name" /></p>
    2638 <p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p>
     2636<p class="required">First name: <input type="text" name="first_name" /></p>
     2637<p class="required">Last name: <input type="text" name="last_name" /></p>
     2638<p class="required">Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p>
    26392639
    26402640With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label.
    26412641>>> p = Person(auto_id='id_%s')
    26422642>>> print p
    2643 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
    2644 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
    2645 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr>
     2643<tr class="required"><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
     2644<tr class="required"><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
     2645<tr class="required"><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr>
    26462646>>> print p.as_ul()
    2647 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
    2648 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
    2649 <li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></li>
     2647<li class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
     2648<li class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
     2649<li class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></li>
    26502650>>> print p.as_p()
    2651 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
    2652 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
    2653 <p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></p>
     2651<p class="required"><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
     2652<p class="required"><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
     2653<p class="required"><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></p>
    26542654
    26552655If a field with a HiddenInput has errors, the as_table() and as_ul() output
    26562656will include the error message(s) with the text "(Hidden field [fieldname]) "
     
    26592659>>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}, auto_id=False)
    26602660>>> print p
    26612661<tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr>
    2662 <tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr>
    2663 <tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr>
    2664 <tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr>
     2662<tr class="required"><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr>
     2663<tr class="required"><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr>
     2664<tr class="required"><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr>
    26652665>>> print p.as_ul()
    26662666<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li>
    2667 <li>First name: <input type="text" name="first_name" value="John" /></li>
    2668 <li>Last name: <input type="text" name="last_name" value="Lennon" /></li>
    2669 <li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li>
     2667<li class="required">First name: <input type="text" name="first_name" value="John" /></li>
     2668<li class="required">Last name: <input type="text" name="last_name" value="Lennon" /></li>
     2669<li class="required">Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li>
    26702670>>> print p.as_p()
    26712671<p><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></p>
    2672 <p>First name: <input type="text" name="first_name" value="John" /></p>
    2673 <p>Last name: <input type="text" name="last_name" value="Lennon" /></p>
    2674 <p>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p>
     2672<p class="required">First name: <input type="text" name="first_name" value="John" /></p>
     2673<p class="required">Last name: <input type="text" name="last_name" value="Lennon" /></p>
     2674<p class="required">Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p>
    26752675
    26762676A corner case: It's possible for a form to have only HiddenInputs.
    26772677>>> class TestForm(Form):
     
    27032703...     field14 = CharField()
    27042704>>> p = TestForm(auto_id=False)
    27052705>>> print p
    2706 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
    2707 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
    2708 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
    2709 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
    2710 <tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr>
    2711 <tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr>
    2712 <tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr>
    2713 <tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr>
    2714 <tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr>
    2715 <tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr>
    2716 <tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr>
    2717 <tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr>
    2718 <tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr>
    2719 <tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr>
     2706<tr class="required"><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
     2707<tr class="required"><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
     2708<tr class="required"><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
     2709<tr class="required"><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
     2710<tr class="required"><th>Field5:</th><td><input type="text" name="field5" /></td></tr>
     2711<tr class="required"><th>Field6:</th><td><input type="text" name="field6" /></td></tr>
     2712<tr class="required"><th>Field7:</th><td><input type="text" name="field7" /></td></tr>
     2713<tr class="required"><th>Field8:</th><td><input type="text" name="field8" /></td></tr>
     2714<tr class="required"><th>Field9:</th><td><input type="text" name="field9" /></td></tr>
     2715<tr class="required"><th>Field10:</th><td><input type="text" name="field10" /></td></tr>
     2716<tr class="required"><th>Field11:</th><td><input type="text" name="field11" /></td></tr>
     2717<tr class="required"><th>Field12:</th><td><input type="text" name="field12" /></td></tr>
     2718<tr class="required"><th>Field13:</th><td><input type="text" name="field13" /></td></tr>
     2719<tr class="required"><th>Field14:</th><td><input type="text" name="field14" /></td></tr>
    27202720
    27212721Some Field classes have an effect on the HTML attributes of their associated
    27222722Widget. If you set max_length in a CharField and its associated widget is
     
    27292729...    address = CharField()                                 # no max_length defined here
    27302730>>> p = UserRegistration(auto_id=False)
    27312731>>> print p.as_ul()
    2732 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2733 <li>Password: <input type="password" name="password" maxlength="10" /></li>
    2734 <li>Realname: <input type="text" name="realname" maxlength="10" /></li>
    2735 <li>Address: <input type="text" name="address" /></li>
     2732<li class="required">Username: <input type="text" name="username" maxlength="10" /></li>
     2733<li class="required">Password: <input type="password" name="password" maxlength="10" /></li>
     2734<li class="required">Realname: <input type="text" name="realname" maxlength="10" /></li>
     2735<li class="required">Address: <input type="text" name="address" /></li>
    27362736
    27372737If you specify a custom "attrs" that includes the "maxlength" attribute,
    27382738the Field's max_length attribute will override whatever "maxlength" you specify
     
    27422742...    password = CharField(max_length=10, widget=PasswordInput)
    27432743>>> p = UserRegistration(auto_id=False)
    27442744>>> print p.as_ul()
    2745 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2746 <li>Password: <input type="password" name="password" maxlength="10" /></li>
     2745<li class="required">Username: <input type="text" name="username" maxlength="10" /></li>
     2746<li class="required">Password: <input type="password" name="password" maxlength="10" /></li>
    27472747
    27482748# Specifying labels ###########################################################
    27492749
     
    27562756...    password2 = CharField(widget=PasswordInput, label='Password (again)')
    27572757>>> p = UserRegistration(auto_id=False)
    27582758>>> print p.as_ul()
    2759 <li>Your username: <input type="text" name="username" maxlength="10" /></li>
    2760 <li>Password1: <input type="password" name="password1" /></li>
    2761 <li>Password (again): <input type="password" name="password2" /></li>
     2759<li class="required">Your username: <input type="text" name="username" maxlength="10" /></li>
     2760<li class="required">Password1: <input type="password" name="password1" /></li>
     2761<li class="required">Password (again): <input type="password" name="password2" /></li>
    27622762
    27632763Labels for as_* methods will only end in a colon if they don't end in other
    27642764punctuation already.
     
    27692769...    q4 = CharField(label='Answer this question!')
    27702770...    q5 = CharField(label='The last question. Period.')
    27712771>>> print Questions(auto_id=False).as_p()
    2772 <p>The first question: <input type="text" name="q1" /></p>
    2773 <p>What is your name? <input type="text" name="q2" /></p>
    2774 <p>The answer to life is: <input type="text" name="q3" /></p>
    2775 <p>Answer this question! <input type="text" name="q4" /></p>
    2776 <p>The last question. Period. <input type="text" name="q5" /></p>
     2772<p class="required">The first question: <input type="text" name="q1" /></p>
     2773<p class="required">What is your name? <input type="text" name="q2" /></p>
     2774<p class="required">The answer to life is: <input type="text" name="q3" /></p>
     2775<p class="required">Answer this question! <input type="text" name="q4" /></p>
     2776<p class="required">The last question. Period. <input type="text" name="q5" /></p>
    27772777>>> print Questions().as_p()
    2778 <p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p>
    2779 <p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p>
    2780 <p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p>
    2781 <p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p>
    2782 <p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p>
     2778<p class="required"><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p>
     2779<p class="required"><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p>
     2780<p class="required"><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p>
     2781<p class="required"><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p>
     2782<p class="required"><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p>
    27832783
    27842784A label can be a Unicode object or a bytestring with special characters.
    27852785>>> class UserRegistration(Form):
     
    27872787...    password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
    27882788>>> p = UserRegistration(auto_id=False)
    27892789>>> p.as_ul()
    2790 u'<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="text" name="username" maxlength="10" /></li>\n<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="password" name="password" /></li>'
     2790u'<li class="required">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="text" name="username" maxlength="10" /></li>\n<li class="required">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="password" name="password" /></li>'
    27912791
    27922792If a label is set to the empty string for a field, that field won't get a label.
    27932793>>> class UserRegistration(Form):
     
    27952795...    password = CharField(widget=PasswordInput)
    27962796>>> p = UserRegistration(auto_id=False)
    27972797>>> print p.as_ul()
    2798 <li> <input type="text" name="username" maxlength="10" /></li>
    2799 <li>Password: <input type="password" name="password" /></li>
     2798<li class="required"> <input type="text" name="username" maxlength="10" /></li>
     2799<li class="required">Password: <input type="password" name="password" /></li>
    28002800>>> p = UserRegistration(auto_id='id_%s')
    28012801>>> print p.as_ul()
    2802 <li> <input id="id_username" type="text" name="username" maxlength="10" /></li>
    2803 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
     2802<li class="required"> <input id="id_username" type="text" name="username" maxlength="10" /></li>
     2803<li class="required"><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
    28042804
    28052805If label is None, Django will auto-create the label from the field name. This
    28062806is default behavior.
     
    28092809...    password = CharField(widget=PasswordInput)
    28102810>>> p = UserRegistration(auto_id=False)
    28112811>>> print p.as_ul()
    2812 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2813 <li>Password: <input type="password" name="password" /></li>
     2812<li class="required">Username: <input type="text" name="username" maxlength="10" /></li>
     2813<li class="required">Password: <input type="password" name="password" /></li>
    28142814>>> p = UserRegistration(auto_id='id_%s')
    28152815>>> print p.as_ul()
    2816 <li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li>
    2817 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
     2816<li class="required"><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li>
     2817<li class="required"><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
    28182818
    28192819# Initial data ################################################################
    28202820
     
    28302830Here, we're not submitting any data, so the initial value will be displayed.
    28312831>>> p = UserRegistration(auto_id=False)
    28322832>>> print p.as_ul()
    2833 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
    2834 <li>Password: <input type="password" name="password" /></li>
     2833<li class="required">Username: <input type="text" name="username" value="django" maxlength="10" /></li>
     2834<li class="required">Password: <input type="password" name="password" /></li>
    28352835
    28362836Here, we're submitting data, so the initial value will *not* be displayed.
    28372837>>> p = UserRegistration({}, auto_id=False)
    28382838>>> print p.as_ul()
    2839 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2840 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2839<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2840<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28412841>>> p = UserRegistration({'username': u''}, auto_id=False)
    28422842>>> print p.as_ul()
    2843 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2844 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2843<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2844<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28452845>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
    28462846>>> print p.as_ul()
    2847 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
    2848 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2847<li class="required">Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
     2848<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28492849
    28502850An 'initial' value is *not* used as a fallback if data is not provided. In this
    28512851example, we don't provide a value for 'username', and the form raises a
     
    28712871Here, we're not submitting any data, so the initial value will be displayed.
    28722872>>> p = UserRegistration(initial={'username': 'django'}, auto_id=False)
    28732873>>> print p.as_ul()
    2874 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
    2875 <li>Password: <input type="password" name="password" /></li>
     2874<li class="required">Username: <input type="text" name="username" value="django" maxlength="10" /></li>
     2875<li class="required">Password: <input type="password" name="password" /></li>
    28762876>>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False)
    28772877>>> print p.as_ul()
    2878 <li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
    2879 <li>Password: <input type="password" name="password" /></li>
     2878<li class="required">Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
     2879<li class="required">Password: <input type="password" name="password" /></li>
    28802880
    28812881The 'initial' parameter is meaningless if you pass data.
    28822882>>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False)
    28832883>>> print p.as_ul()
    2884 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2885 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2884<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2885<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28862886>>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False)
    28872887>>> print p.as_ul()
    2888 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2889 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2888<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2889<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28902890>>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False)
    28912891>>> print p.as_ul()
    2892 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
    2893 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2892<li class="required">Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
     2893<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    28942894
    28952895A dynamic 'initial' value is *not* used as a fallback if data is not provided.
    28962896In this example, we don't provide a value for 'username', and the form raises a
     
    29082908...    password = CharField(widget=PasswordInput)
    29092909>>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False)
    29102910>>> print p.as_ul()
    2911 <li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
    2912 <li>Password: <input type="password" name="password" /></li>
     2911<li class="required">Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
     2912<li class="required">Password: <input type="password" name="password" /></li>
    29132913
    29142914# Callable initial data ########################################################
    29152915
     
    29292929Here, we're not submitting any data, so the initial value will be displayed.
    29302930>>> p = UserRegistration(initial={'username': initial_django}, auto_id=False)
    29312931>>> print p.as_ul()
    2932 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
    2933 <li>Password: <input type="password" name="password" /></li>
     2932<li class="required">Username: <input type="text" name="username" value="django" maxlength="10" /></li>
     2933<li class="required">Password: <input type="password" name="password" /></li>
    29342934
    29352935The 'initial' parameter is meaningless if you pass data.
    29362936>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False)
    29372937>>> print p.as_ul()
    2938 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2939 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2938<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2939<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    29402940>>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False)
    29412941>>> print p.as_ul()
    2942 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2943 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2942<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
     2943<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    29442944>>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False)
    29452945>>> print p.as_ul()
    2946 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
    2947 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2946<li class="required">Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
     2947<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
    29482948
    29492949A callable 'initial' value is *not* used as a fallback if data is not provided.
    29502950In this example, we don't provide a value for 'username', and the form raises a
     
    29622962...    password = CharField(widget=PasswordInput)
    29632963>>> p = UserRegistration(auto_id=False)
    29642964>>> print p.as_ul()
    2965 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
    2966 <li>Password: <input type="password" name="password" /></li>
     2965<li class="required">Username: <input type="text" name="username" value="django" maxlength="10" /></li>
     2966<li class="required">Password: <input type="password" name="password" /></li>
    29672967>>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False)
    29682968>>> print p.as_ul()
    2969 <li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
    2970 <li>Password: <input type="password" name="password" /></li>
     2969<li class="required">Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
     2970<li class="required">Password: <input type="password" name="password" /></li>
    29712971
    29722972# Help text ###################################################################
    29732973
     
    29782978...    password = CharField(widget=PasswordInput, help_text='Choose wisely.')
    29792979>>> p = UserRegistration(auto_id=False)
    29802980>>> print p.as_ul()
    2981 <li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
    2982 <li>Password: <input type="password" name="password" /> Choose wisely.</li>
     2981<li class="required">Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
     2982<li class="required">Password: <input type="password" name="password" /> Choose wisely.</li>
    29832983>>> print p.as_p()
    2984 <p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p>
    2985 <p>Password: <input type="password" name="password" /> Choose wisely.</p>
     2984<p class="required">Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p>
     2985<p class="required">Password: <input type="password" name="password" /> Choose wisely.</p>
    29862986>>> print p.as_table()
    2987 <tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr>
    2988 <tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr>
     2987<tr class="required"><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr>
     2988<tr class="required"><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr>
    29892989
    29902990The help text is displayed whether or not data is provided for the form.
    29912991>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
    29922992>>> print p.as_ul()
    2993 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li>
    2994 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li>
     2993<li class="required">Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li>
     2994<li class="error required"><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li>
    29952995
    29962996help_text is not displayed for hidden fields. It can be used for documentation
    29972997purposes, though.
     
    30013001...    next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination')
    30023002>>> p = UserRegistration(auto_id=False)
    30033003>>> print p.as_ul()
    3004 <li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
    3005 <li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li>
     3004<li class="required">Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
     3005<li class="required">Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li>
    30063006
    30073007Help text can include arbitrary Unicode characters.
    30083008>>> class UserRegistration(Form):
    30093009...    username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ')
    30103010>>> p = UserRegistration(auto_id=False)
    30113011>>> p.as_ul()
    3012 u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>'
     3012u'<li class="required">Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>'
    30133013
    30143014# Subclassing forms ###########################################################
    30153015
     
    30243024...     instrument = CharField()
    30253025>>> p = Person(auto_id=False)
    30263026>>> print p.as_ul()
    3027 <li>First name: <input type="text" name="first_name" /></li>
    3028 <li>Last name: <input type="text" name="last_name" /></li>
    3029 <li>Birthday: <input type="text" name="birthday" /></li>
     3027<li class="required">First name: <input type="text" name="first_name" /></li>
     3028<li class="required">Last name: <input type="text" name="last_name" /></li>
     3029<li class="required">Birthday: <input type="text" name="birthday" /></li>
    30303030>>> m = Musician(auto_id=False)
    30313031>>> print m.as_ul()
    3032 <li>First name: <input type="text" name="first_name" /></li>
    3033 <li>Last name: <input type="text" name="last_name" /></li>
    3034 <li>Birthday: <input type="text" name="birthday" /></li>
    3035 <li>Instrument: <input type="text" name="instrument" /></li>
     3032<li class="required">First name: <input type="text" name="first_name" /></li>
     3033<li class="required">Last name: <input type="text" name="last_name" /></li>
     3034<li class="required">Birthday: <input type="text" name="birthday" /></li>
     3035<li class="required">Instrument: <input type="text" name="instrument" /></li>
    30363036
    30373037Yes, you can subclass multiple forms. The fields are added in the order in
    30383038which the parent classes are listed.
     
    30463046...     haircut_type = CharField()
    30473047>>> b = Beatle(auto_id=False)
    30483048>>> print b.as_ul()
    3049 <li>First name: <input type="text" name="first_name" /></li>
    3050 <li>Last name: <input type="text" name="last_name" /></li>
    3051 <li>Birthday: <input type="text" name="birthday" /></li>
    3052 <li>Instrument: <input type="text" name="instrument" /></li>
    3053 <li>Haircut type: <input type="text" name="haircut_type" /></li>
     3049<li class="required">First name: <input type="text" name="first_name" /></li>
     3050<li class="required">Last name: <input type="text" name="last_name" /></li>
     3051<li class="required">Birthday: <input type="text" name="birthday" /></li>
     3052<li class="required">Instrument: <input type="text" name="instrument" /></li>
     3053<li class="required">Haircut type: <input type="text" name="haircut_type" /></li>
    30543054
    30553055# Forms with prefixes #########################################################
    30563056
     
    30723072... }
    30733073>>> p = Person(data, prefix='person1')
    30743074>>> print p.as_ul()
    3075 <li><label for="id_person1-first_name">First name:</label> <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li>
    3076 <li><label for="id_person1-last_name">Last name:</label> <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li>
    3077 <li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li>
     3075<li class="required"><label for="id_person1-first_name">First name:</label> <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li>
     3076<li class="required"><label for="id_person1-last_name">Last name:</label> <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li>
     3077<li class="required"><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li>
    30783078>>> print p['first_name']
    30793079<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" />
    30803080>>> print p['last_name']
     
    31493149...         return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name
    31503150>>> p = Person(prefix='foo')
    31513151>>> print p.as_ul()
    3152 <li><label for="id_foo-prefix-first_name">First name:</label> <input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li>
    3153 <li><label for="id_foo-prefix-last_name">Last name:</label> <input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li>
    3154 <li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li>
     3152<li class="required"><label for="id_foo-prefix-first_name">First name:</label> <input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li>
     3153<li class="required"><label for="id_foo-prefix-last_name">Last name:</label> <input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li>
     3154<li class="required"><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li>
    31553155>>> data = {
    31563156...     'foo-prefix-first_name': u'John',
    31573157...     'foo-prefix-last_name': u'Lennon',
     
    32393239>>> print my_function('GET', {})
    32403240<form action="" method="post">
    32413241<table>
    3242 <tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr>
    3243 <tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
    3244 <tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr>
     3242<tr class="required"><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr>
     3243<tr class="required"><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
     3244<tr class="required"><th>Password2:</th><td><input type="password" name="password2" /></td></tr>
    32453245</table>
    32463246<input type="submit" />
    32473247</form>
     
    32513251<form action="" method="post">
    32523252<table>
    32533253<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr>
    3254 <tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters.</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr>
    3255 <tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
    3256 <tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
     3254<tr class="error required"><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters.</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr>
     3255<tr class="required"><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
     3256<tr class="required"><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
    32573257</table>
    32583258<input type="submit" />
    32593259</form>
     
    36013601...     field1 = ComplexField(widget=w)
    36023602>>> f = ComplexFieldForm()
    36033603>>> print f
    3604 <tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
     3604<tr class="required"><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
    36053605<select multiple="multiple" name="field1_1" id="id_field1_1">
    36063606<option value="J">John</option>
    36073607<option value="P">Paul</option>
     
    36123612
    36133613>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
    36143614>>> print f
    3615 <tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
     3615<tr class="required"><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
    36163616<select multiple="multiple" name="field1_1" id="id_field1_1">
    36173617<option value="J" selected="selected">John</option>
    36183618<option value="P" selected="selected">Paul</option>
Back to Top