diff --git a/django/forms/forms.py b/django/forms/forms.py index b81c95f8ad..3a6182611e 100644 --- a/django/forms/forms.py +++ b/django/forms/forms.py @@ -171,6 +171,13 @@ class BaseForm(StrAndUnicode): last_row = output[-1] # Chop off the trailing row_ender (e.g. '') and # insert the hidden fields. + if not last_row.endswith(row_ender): + # This can happen in the as_p() case (and possibly others + # that users write): if there are only top errors, we may + # not be able to conscript the last row for our purposes, + # so insert a new, empty row. + last_row = normal_row % {'errors': '', 'label': '', 'field': '', 'help_text': ''} + output.append(last_row) output[-1] = last_row[:-len(row_ender)] + str_hidden + row_ender else: # If there aren't any rows in the output, just append the diff --git a/tests/regressiontests/forms/regressions.py b/tests/regressiontests/forms/regressions.py index 5e32cd397d..51aa41d2fb 100644 --- a/tests/regressiontests/forms/regressions.py +++ b/tests/regressiontests/forms/regressions.py @@ -88,4 +88,18 @@ doesn't come back. True >>> f.cleaned_data {'data': u'xyzzy'} + +A form with *only* hidden fields that has errors is going to be very unusual. +But we can try to make sure it doesn't generate invalid XHTML. In this case, +the as_p() method is the tricky one, since error lists cannot be nested +(validly) inside p elements. + +>>> class HiddenForm(Form): +... data = IntegerField(widget=HiddenInput) +>>> f = HiddenForm({}) +>>> f.as_p() +u'\n

' +>>> f.as_table() +u'' + """