Ticket #3255: newforms-help_text.diff

File newforms-help_text.diff, 39.2 KB (added by Ben Slavin, 8 years ago)

[patch] adds help_text for newforms

  • django/newforms/fields.py

     
    3333    # Tracks each time a Field instance is created. Used to retain order.
    3434    creation_counter = 0
    3535
    36     def __init__(self, required=True, widget=None, label=None, initial=None):
     36    def __init__(self, required=True, widget=None, label=None, initial=None, help_text=None):
    3737        # required -- Boolean that specifies whether the field is required.
    3838        #             True by default.
    3939        # widget -- A Widget class, or instance of a Widget class, that should be
     
    4747        #            *not* used as a fallback if data isn't given.
    4848        if label is not None:
    4949            label = smart_unicode(label)
    50         self.required, self.label, self.initial = required, label, initial
     50        self.required, self.label, self.initial, self.help_text = required, label, initial, help_text
    5151        widget = widget or self.widget
    5252        if isinstance(widget, type):
    5353            widget = widget()
     
    8383        return {}
    8484
    8585class CharField(Field):
    86     def __init__(self, max_length=None, min_length=None, required=True, widget=None, label=None, initial=None):
     86    def __init__(self, max_length=None, min_length=None, required=True, widget=None, label=None, initial=None, help_text=None):
    8787        self.max_length, self.min_length = max_length, min_length
    88         Field.__init__(self, required, widget, label, initial)
     88        Field.__init__(self, required, widget, label, initial, help_text)
    8989
    9090    def clean(self, value):
    9191        "Validates max_length and min_length. Returns a Unicode object."
     
    106106            return {'maxlength': str(self.max_length)}
    107107
    108108class IntegerField(Field):
    109     def __init__(self, max_value=None, min_value=None, required=True, widget=None, label=None, initial=None):
     109    def __init__(self, max_value=None, min_value=None, required=True, widget=None, label=None, initial=None, help_text=None):
    110110        self.max_value, self.min_value = max_value, min_value
    111         Field.__init__(self, required, widget, label, initial)
     111        Field.__init__(self, required, widget, label, initial, help_text)
    112112
    113113    def clean(self, value):
    114114        """
     
    137137)
    138138
    139139class DateField(Field):
    140     def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None):
    141         Field.__init__(self, required, widget, label, initial)
     140    def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None, help_text=None):
     141        Field.__init__(self, required, widget, label, initial, help_text)
    142142        self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
    143143
    144144    def clean(self, value):
     
    166166)
    167167
    168168class TimeField(Field):
    169     def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None):
    170         Field.__init__(self, required, widget, label, initial)
     169    def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None, help_text=None):
     170        Field.__init__(self, required, widget, label, initial, help_text)
    171171        self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS
    172172
    173173    def clean(self, value):
     
    200200)
    201201
    202202class DateTimeField(Field):
    203     def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None):
    204         Field.__init__(self, required, widget, label, initial)
     203    def __init__(self, input_formats=None, required=True, widget=None, label=None, initial=None, help_text=None):
     204        Field.__init__(self, required, widget, label, initial, help_text)
    205205        self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
    206206
    207207    def clean(self, value):
     
    225225
    226226class RegexField(Field):
    227227    def __init__(self, regex, max_length=None, min_length=None, error_message=None,
    228             required=True, widget=None, label=None, initial=None):
     228            required=True, widget=None, label=None, initial=None, help_text=None):
    229229        """
    230230        regex can be either a string or a compiled regular expression object.
    231231        error_message is an optional error message to use, if
     
    262262    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
    263263
    264264class EmailField(RegexField):
    265     def __init__(self, max_length=None, min_length=None, required=True, widget=None, label=None, initial=None):
    266         RegexField.__init__(self, email_re, max_length, min_length, gettext(u'Enter a valid e-mail address.'), required, widget, label, initial)
     265    def __init__(self, max_length=None, min_length=None, required=True, widget=None, label=None, initial=None, help_text=None):
     266        RegexField.__init__(self, email_re, max_length, min_length, gettext(u'Enter a valid e-mail address.'), required, widget, label, initial, help_text)
    267267
    268268url_re = re.compile(
    269269    r'^https?://' # http:// or https://
     
    280280
    281281class URLField(RegexField):
    282282    def __init__(self, max_length=None, min_length=None, required=True, verify_exists=False, widget=None, label=None,
    283             initial=None, validator_user_agent=URL_VALIDATOR_USER_AGENT):
    284         RegexField.__init__(self, url_re, max_length, min_length, gettext(u'Enter a valid URL.'), required, widget, label, initial)
     283            initial=None, validator_user_agent=URL_VALIDATOR_USER_AGENT, help_text=None):
     284        RegexField.__init__(self, url_re, max_length, min_length, gettext(u'Enter a valid URL.'), required, widget, label, initial, help_text)
    285285        self.verify_exists = verify_exists
    286286        self.user_agent = validator_user_agent
    287287
     
    315315        return bool(value)
    316316
    317317class ChoiceField(Field):
    318     def __init__(self, choices=(), required=True, widget=Select, label=None, initial=None):
     318    def __init__(self, choices=(), required=True, widget=Select, label=None, initial=None, help_text=None):
    319319        if isinstance(widget, type):
    320320            widget = widget(choices=choices)
    321         Field.__init__(self, required, widget, label, initial)
     321        Field.__init__(self, required, widget, label, initial, help_text)
    322322        self.choices = choices
    323323
    324324    def clean(self, value):
     
    336336        return value
    337337
    338338class MultipleChoiceField(ChoiceField):
    339     def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None):
    340         ChoiceField.__init__(self, choices, required, widget, label, initial)
     339    def __init__(self, choices=(), required=True, widget=SelectMultiple, label=None, initial=None, help_text=None):
     340        ChoiceField.__init__(self, choices, required, widget, label, initial, help_text)
    341341
    342342    def clean(self, value):
    343343        """
     
    361361        return new_value
    362362
    363363class ComboField(Field):
    364     def __init__(self, fields=(), required=True, widget=None, label=None, initial=None):
    365         Field.__init__(self, required, widget, label, initial)
     364    def __init__(self, fields=(), required=True, widget=None, label=None, initial=None, help_text=None):
     365        Field.__init__(self, required, widget, label, initial, help_text)
    366366        # Set 'required' to False on the individual fields, because the
    367367        # required validation will be handled by ComboField, not by those
    368368        # individual fields.
  • django/newforms/forms.py

     
    8484        """
    8585        return self.prefix and ('%s-%s' % (self.prefix, field_name)) or field_name
    8686
    87     def _html_output(self, normal_row, error_row, row_ender, errors_on_separate_row):
     87    def _html_output(self, normal_row, error_row, help_row, row_ender, errors_on_separate_row, help_on_separate_row):
    8888        "Helper function for outputting HTML. Used by as_table(), as_ul(), as_p()."
    8989        top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
    9090        output, hidden_fields = [], []
    9191        for name, field in self.fields.items():
    9292            bf = BoundField(self, field, name)
    9393            bf_errors = bf.errors # Cache in local variable.
     94            bf_help_text = bf.field.help_text or ''
    9495            if bf.is_hidden:
    9596                if bf_errors:
    9697                    top_errors.extend(['(Hidden field %s) %s' % (name, e) for e in bf_errors])
     
    99100                if errors_on_separate_row and bf_errors:
    100101                    output.append(error_row % bf_errors)
    101102                label = bf.label and bf.label_tag(escape(bf.label + ':')) or ''
    102                 output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': bf})
     103                output.append(normal_row % {'errors': bf_errors, 'label': label, 'field': bf, 'help_text': bf_help_text})
     104                if help_on_separate_row and bf_help_text:
     105                    output.append(help_row % bf_help_text)
    103106        if top_errors:
    104107            output.insert(0, error_row % top_errors)
    105108        if hidden_fields: # Insert any hidden fields in the last row.
     
    114117
    115118    def as_table(self):
    116119        "Returns this form rendered as HTML <tr>s -- excluding the <table></table>."
    117         return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', False)
     120        return self._html_output(u'<tr><th>%(label)s</th><td>%(errors)s%(field)s</td></tr>', u'<tr><td colspan="2">%s</td></tr>',
     121            u'<tr><td colspan="2">%s</td></tr>', '</td></tr>', False, True)
    118122
    119123    def as_ul(self):
    120124        "Returns this form rendered as HTML <li>s -- excluding the <ul></ul>."
    121         return self._html_output(u'<li>%(errors)s%(label)s %(field)s</li>', u'<li>%s</li>', '</li>', False)
     125        return self._html_output(u'<li>%(errors)s%(label)s %(field)s %(help_text)s</li>', u'<li>%s</li>', u'<li>%s</li>', '</li>', False, False)
    122126
    123127    def as_p(self):
    124128        "Returns this form rendered as HTML <p>s."
    125         return self._html_output(u'<p>%(label)s %(field)s</p>', u'<p>%s</p>', '</p>', True)
     129        return self._html_output(u'<p>%(label)s %(field)s</p>', u'<p>%s</p>', u'<p>%s</p>', '</p>', True, True)
    126130
    127131    def non_field_errors(self):
    128132        """
  • tests/modeltests/model_forms/models.py

     
    5656<tr><th><label for="id_name">Name:</label></th><td><input id="id_name" type="text" name="name" maxlength="20" /></td></tr>
    5757<tr><th><label for="id_url">The URL:</label></th><td><input id="id_url" type="text" name="url" maxlength="40" /></td></tr>
    5858>>> print f.as_ul()
    59 <li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /></li>
    60 <li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /></li>
     59<li><label for="id_name">Name:</label> <input id="id_name" type="text" name="name" maxlength="20" /> </li>
     60<li><label for="id_url">The URL:</label> <input id="id_url" type="text" name="url" maxlength="40" /> </li>
    6161>>> print f['name']
    6262<input id="id_name" type="text" name="name" maxlength="20" />
    6363
    6464>>> f = CategoryForm(auto_id=False)
    6565>>> print f.as_ul()
    66 <li>Name: <input type="text" name="name" maxlength="20" /></li>
    67 <li>The URL: <input type="text" name="url" maxlength="40" /></li>
     66<li>Name: <input type="text" name="name" maxlength="20" /> </li>
     67<li>The URL: <input type="text" name="url" maxlength="40" /> </li>
    6868
    6969>>> f = CategoryForm({'name': 'Entertainment', 'url': 'entertainment'})
    7070>>> f.is_valid()
     
    173173>>> TestArticleForm = form_for_instance(art)
    174174>>> f = TestArticleForm(auto_id=False)
    175175>>> print f.as_ul()
    176 <li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /></li>
    177 <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     176<li>Headline: <input type="text" name="headline" value="Test article" maxlength="50" /> </li>
     177<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /> </li>
    178178<li>Writer: <select name="writer">
    179179<option value="">---------</option>
    180180<option value="1" selected="selected">Mike Royko</option>
    181181<option value="2">Bob Woodward</option>
    182 </select></li>
     182</select> </li>
    183183<li>Categories: <select multiple="multiple" name="categories">
    184184<option value="1">Entertainment</option>
    185185<option value="2">It&#39;s a test</option>
    186186<option value="3">Third test</option>
    187 </select></li>
     187</select> </li>
    188188>>> f = TestArticleForm({'headline': u'New headline', 'pub_date': u'1988-01-04', 'writer': u'1'})
    189189>>> f.is_valid()
    190190True
     
    204204>>> TestArticleForm = form_for_instance(new_art)
    205205>>> f = TestArticleForm(auto_id=False)
    206206>>> print f.as_ul()
    207 <li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /></li>
    208 <li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /></li>
     207<li>Headline: <input type="text" name="headline" value="New headline" maxlength="50" /> </li>
     208<li>Pub date: <input type="text" name="pub_date" value="1988-01-04" /> </li>
    209209<li>Writer: <select name="writer">
    210210<option value="">---------</option>
    211211<option value="1" selected="selected">Mike Royko</option>
    212212<option value="2">Bob Woodward</option>
    213 </select></li>
     213</select> </li>
    214214<li>Categories: <select multiple="multiple" name="categories">
    215215<option value="1" selected="selected">Entertainment</option>
    216216<option value="2">It&#39;s a test</option>
    217217<option value="3">Third test</option>
    218 </select></li>
     218</select> </li>
    219219
    220220"""}
  • tests/regressiontests/forms/tests.py

     
    15611561<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>
    15621562<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>
    15631563>>> print p.as_ul()
    1564 <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>
    1565 <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>
    1566 <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>
     1564<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>
     1565<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>
     1566<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>
    15671567>>> print p.as_p()
    15681568<p><ul class="errorlist"><li>This field is required.</li></ul></p>
    15691569<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
     
    15951595<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
    15961596<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
    15971597>>> print p.as_ul()
    1598 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
    1599 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
    1600 <li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
     1598<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /> </li>
     1599<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /> </li>
     1600<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /> </li>
    16011601>>> print p.as_p()
    16021602<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
    16031603<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
     
    16081608>>> p.as_table()
    16091609u'<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>'
    16101610>>> p.as_ul()
    1611 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>'
     1611u'<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>'
    16121612>>> p.as_p()
    16131613u'<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>'
    16141614
     
    16531653<tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr>
    16541654<tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr>
    16551655>>> print p.as_ul()
    1656 <li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li>
    1657 <li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li>
    1658 <li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li>
     1656<li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /> </li>
     1657<li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /> </li>
     1658<li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /> </li>
    16591659>>> print p.as_p()
    16601660<p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p>
    16611661<p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p>
     
    16651665attribute will be the name of the field.
    16661666>>> p = Person(auto_id=True)
    16671667>>> print p.as_ul()
    1668 <li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li>
    1669 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
    1670 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
     1668<li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /> </li>
     1669<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /> </li>
     1670<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /> </li>
    16711671
    16721672If auto_id is any False value, an "id" attribute won't be output unless it
    16731673was manually entered.
    16741674>>> p = Person(auto_id=False)
    16751675>>> print p.as_ul()
    1676 <li>First name: <input type="text" name="first_name" /></li>
    1677 <li>Last name: <input type="text" name="last_name" /></li>
    1678 <li>Birthday: <input type="text" name="birthday" /></li>
     1676<li>First name: <input type="text" name="first_name" /> </li>
     1677<li>Last name: <input type="text" name="last_name" /> </li>
     1678<li>Birthday: <input type="text" name="birthday" /> </li>
    16791679
    16801680In this example, auto_id is False, but the "id" attribute for the "first_name"
    16811681field is given. Also note that field gets a <label>, while the others don't.
     
    16851685...     birthday = DateField()
    16861686>>> p = PersonNew(auto_id=False)
    16871687>>> print p.as_ul()
    1688 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
    1689 <li>Last name: <input type="text" name="last_name" /></li>
    1690 <li>Birthday: <input type="text" name="birthday" /></li>
     1688<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /> </li>
     1689<li>Last name: <input type="text" name="last_name" /> </li>
     1690<li>Birthday: <input type="text" name="birthday" /> </li>
    16911691
    16921692If the "id" attribute is specified in the Form and auto_id is True, the "id"
    16931693attribute in the Form gets precedence.
    16941694>>> p = PersonNew(auto_id=True)
    16951695>>> print p.as_ul()
    1696 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
    1697 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
    1698 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
     1696<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /> </li>
     1697<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /> </li>
     1698<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /> </li>
    16991699
    17001700>>> class SignupForm(Form):
    17011701...     email = EmailField()
     
    17851785<li><label><input type="radio" name="language" value="J" /> Java</label></li>
    17861786</ul></td></tr>
    17871787>>> print f.as_ul()
    1788 <li>Name: <input type="text" name="name" /></li>
     1788<li>Name: <input type="text" name="name" /> </li>
    17891789<li>Language: <ul>
    17901790<li><label><input type="radio" name="language" value="P" /> Python</label></li>
    17911791<li><label><input type="radio" name="language" value="J" /> Java</label></li>
    1792 </ul></li>
     1792</ul> </li>
    17931793
    17941794Regarding auto_id and <label>, RadioSelect is a special case. Each radio button
    17951795gets a distinct ID, formed by appending an underscore plus the button's
     
    18111811<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
    18121812</ul></td></tr>
    18131813>>> print f.as_ul()
    1814 <li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
     1814<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /> </li>
    18151815<li><label for="id_language_0">Language:</label> <ul>
    18161816<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
    18171817<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
    1818 </ul></li>
     1818</ul> </li>
    18191819>>> print f.as_p()
    18201820<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p>
    18211821<p><label for="id_language_0">Language:</label> <ul>
     
    19701970<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
    19711971>>> print f.as_ul()
    19721972<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li>
    1973 <li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>
    1974 <li>Password1: <input type="password" name="password1" value="foo" /></li>
    1975 <li>Password2: <input type="password" name="password2" value="bar" /></li>
     1973<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /> </li>
     1974<li>Password1: <input type="password" name="password1" value="foo" /> </li>
     1975<li>Password2: <input type="password" name="password2" value="bar" /> </li>
    19761976>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
    19771977>>> f.errors
    19781978{}
     
    20092009<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
    20102010<tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr>
    20112011>>> print p.as_ul()
    2012 <li>First name: <input type="text" name="first_name" /></li>
    2013 <li>Last name: <input type="text" name="last_name" /></li>
    2014 <li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li>
     2012<li>First name: <input type="text" name="first_name" /> </li>
     2013<li>Last name: <input type="text" name="last_name" /> </li>
     2014<li>Birthday: <input type="text" name="birthday" /> <input type="hidden" name="hidden_text" /></li>
    20152015>>> print p.as_p()
    20162016<p>First name: <input type="text" name="first_name" /></p>
    20172017<p>Last name: <input type="text" name="last_name" /></p>
     
    20242024<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
    20252025<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>
    20262026>>> print p.as_ul()
    2027 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
    2028 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
    2029 <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>
     2027<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /> </li>
     2028<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /> </li>
     2029<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>
    20302030>>> print p.as_p()
    20312031<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
    20322032<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
     
    20442044<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr>
    20452045>>> print p.as_ul()
    20462046<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li>
    2047 <li>First name: <input type="text" name="first_name" value="John" /></li>
    2048 <li>Last name: <input type="text" name="last_name" value="Lennon" /></li>
    2049 <li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li>
     2047<li>First name: <input type="text" name="first_name" value="John" /> </li>
     2048<li>Last name: <input type="text" name="last_name" value="Lennon" /> </li>
     2049<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /> <input type="hidden" name="hidden_text" /></li>
    20502050>>> print p.as_p()
    20512051<p><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></p>
    20522052<p>First name: <input type="text" name="first_name" value="John" /></p>
     
    21092109...    address = CharField()                                 # no max_length defined here
    21102110>>> p = UserRegistration(auto_id=False)
    21112111>>> print p.as_ul()
    2112 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2113 <li>Password: <input type="password" name="password" maxlength="10" /></li>
    2114 <li>Realname: <input type="text" name="realname" maxlength="10" /></li>
    2115 <li>Address: <input type="text" name="address" /></li>
     2112<li>Username: <input type="text" name="username" maxlength="10" /> </li>
     2113<li>Password: <input type="password" name="password" maxlength="10" /> </li>
     2114<li>Realname: <input type="text" name="realname" maxlength="10" /> </li>
     2115<li>Address: <input type="text" name="address" /> </li>
    21162116
    21172117If you specify a custom "attrs" that includes the "maxlength" attribute,
    21182118the Field's max_length attribute will override whatever "maxlength" you specify
     
    21222122...    password = CharField(max_length=10, widget=PasswordInput)
    21232123>>> p = UserRegistration(auto_id=False)
    21242124>>> print p.as_ul()
    2125 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2126 <li>Password: <input type="password" name="password" maxlength="10" /></li>
     2125<li>Username: <input type="text" name="username" maxlength="10" /> </li>
     2126<li>Password: <input type="password" name="password" maxlength="10" /> </li>
    21272127
    21282128# Specifying labels ###########################################################
    21292129
     
    21362136...    password2 = CharField(widget=PasswordInput, label='Password (again)')
    21372137>>> p = UserRegistration(auto_id=False)
    21382138>>> print p.as_ul()
    2139 <li>Your username: <input type="text" name="username" maxlength="10" /></li>
    2140 <li>Password1: <input type="password" name="password1" /></li>
    2141 <li>Password (again): <input type="password" name="password2" /></li>
     2139<li>Your username: <input type="text" name="username" maxlength="10" /> </li>
     2140<li>Password1: <input type="password" name="password1" /> </li>
     2141<li>Password (again): <input type="password" name="password2" /> </li>
    21422142
    21432143A label can be a Unicode object or a bytestring with special characters.
    21442144>>> class UserRegistration(Form):
     
    21462146...    password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
    21472147>>> p = UserRegistration(auto_id=False)
    21482148>>> p.as_ul()
    2149 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>'
     2149u'<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>'
    21502150
    21512151If a label is set to the empty string for a field, that field won't get a label.
    21522152>>> class UserRegistration(Form):
     
    21542154...    password = CharField(widget=PasswordInput)
    21552155>>> p = UserRegistration(auto_id=False)
    21562156>>> print p.as_ul()
    2157 <li> <input type="text" name="username" maxlength="10" /></li>
    2158 <li>Password: <input type="password" name="password" /></li>
     2157<li> <input type="text" name="username" maxlength="10" /> </li>
     2158<li>Password: <input type="password" name="password" /> </li>
    21592159>>> p = UserRegistration(auto_id='id_%s')
    21602160>>> print p.as_ul()
    2161 <li> <input id="id_username" type="text" name="username" maxlength="10" /></li>
    2162 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
     2161<li> <input id="id_username" type="text" name="username" maxlength="10" /> </li>
     2162<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /> </li>
    21632163
    21642164If label is None, Django will auto-create the label from the field name. This
    21652165is default behavior.
     
    21682168...    password = CharField(widget=PasswordInput)
    21692169>>> p = UserRegistration(auto_id=False)
    21702170>>> print p.as_ul()
    2171 <li>Username: <input type="text" name="username" maxlength="10" /></li>
    2172 <li>Password: <input type="password" name="password" /></li>
     2171<li>Username: <input type="text" name="username" maxlength="10" /> </li>
     2172<li>Password: <input type="password" name="password" /> </li>
    21732173>>> p = UserRegistration(auto_id='id_%s')
    21742174>>> print p.as_ul()
    2175 <li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li>
    2176 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
     2175<li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /> </li>
     2176<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /> </li>
    21772177
    21782178# Initial data ################################################################
    21792179
     
    21892189Here, we're not submitting any data, so the initial value will be displayed.
    21902190>>> p = UserRegistration(auto_id=False)
    21912191>>> print p.as_ul()
    2192 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
    2193 <li>Password: <input type="password" name="password" /></li>
     2192<li>Username: <input type="text" name="username" value="django" maxlength="10" /> </li>
     2193<li>Password: <input type="password" name="password" /> </li>
    21942194
    21952195Here, we're submitting data, so the initial value will *not* be displayed.
    21962196>>> p = UserRegistration({}, auto_id=False)
    21972197>>> print p.as_ul()
    2198 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2199 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2198<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /> </li>
     2199<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> </li>
    22002200>>> p = UserRegistration({'username': u''}, auto_id=False)
    22012201>>> print p.as_ul()
    2202 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
    2203 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2202<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /> </li>
     2203<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> </li>
    22042204>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
    22052205>>> print p.as_ul()
    2206 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
    2207 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
     2206<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> </li>
     2207<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> </li>
    22082208
    22092209An 'initial' value is *not* used as a fallback if data is not provided. In this
    22102210example, we don't provide a value for 'username', and the form raises a
     
    22152215>>> p.is_valid()
    22162216False
    22172217
     2218# Help text ###################################################################
     2219
     2220You can specify descriptive text for a field by using the 'help_text' argument
     2221to a Field class. This help text is displayed when a Form is rendered.
     2222>>> class UserRegistration(Form):
     2223...    username = CharField(max_length=10, help_text='Ex. user@example.com')
     2224...    password = CharField(widget=PasswordInput)
     2225
     2226Help text is presented verbatim in all as_*() methods.
     2227>>> p = UserRegistration(auto_id=False)
     2228>>> print p.as_ul()
     2229<li>Username: <input type="text" name="username" maxlength="10" /> Ex. user@example.com</li>
     2230<li>Password: <input type="password" name="password" /> </li>
     2231>>> print p.as_p()
     2232<p>Username: <input type="text" name="username" maxlength="10" /></p>
     2233<p>Ex. user@example.com</p>
     2234<p>Password: <input type="password" name="password" /></p>
     2235>>> print p.as_table()
     2236<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr>
     2237<tr><td colspan="2">Ex. user@example.com</td></tr>
     2238<tr><th>Password:</th><td><input type="password" name="password" /></td></tr>
     2239
     2240The help text is displayed wheter or not data is provided for the form.
     2241>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
     2242>>> print p.as_ul()
     2243<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> Ex. user@example.com</li>
     2244<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> </li>
     2245
     2246For hidden fields, help_text is not displayed.  It can be used for documentation purposes though.
     2247>>> class UserRegistration(Form):
     2248...    username = CharField(max_length=10, help_text='Ex. user@example.com')
     2249...    password = CharField(widget=PasswordInput)
     2250...    next = CharField(widget=HiddenInput, initial='/', help_text='Redirect to destination')
     2251>>> p = UserRegistration(auto_id=False)
     2252>>> print p.as_ul()
     2253<li>Username: <input type="text" name="username" maxlength="10" /> Ex. user@example.com</li>
     2254<li>Password: <input type="password" name="password" /> <input type="hidden" name="next" value="/" /></li>
     2255
    22182256# Forms with prefixes #########################################################
    22192257
    22202258Sometimes it's necessary to have multiple forms display on the same HTML page,
     
    22352273... }
    22362274>>> p = Person(data, prefix='person1')
    22372275>>> print p.as_ul()
    2238 <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>
    2239 <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>
    2240 <li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li>
     2276<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>
     2277<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>
     2278<li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /> </li>
    22412279>>> print p['first_name']
    22422280<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" />
    22432281>>> print p['last_name']
     
    23122350...         return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name
    23132351>>> p = Person(prefix='foo')
    23142352>>> print p.as_ul()
    2315 <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>
    2316 <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>
    2317 <li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li>
     2353<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>
     2354<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>
     2355<li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /> </li>
    23182356>>> data = {
    23192357...     'foo-prefix-first_name': u'John',
    23202358...     'foo-prefix-last_name': u'Lennon',
Back to Top