mirror of
https://github.com/django/django.git
synced 2025-03-12 10:22:37 +00:00
Refs #31026 -- Removed BaseForm._html_output() per deprecation timeline.
This commit is contained in:
parent
4982958ec0
commit
182d25eb7a
@ -13,7 +13,6 @@ from django.forms.widgets import Media, MediaDefiningClass
|
|||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
from django.utils.deprecation import RemovedInDjango50Warning
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.html import conditional_escape
|
|
||||||
from django.utils.safestring import SafeString, mark_safe
|
from django.utils.safestring import SafeString, mark_safe
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
@ -219,99 +218,6 @@ class BaseForm(RenderableFormMixin):
|
|||||||
# widgets split data over several HTML fields.
|
# widgets split data over several HTML fields.
|
||||||
return widget.value_from_datadict(self.data, self.files, html_name)
|
return widget.value_from_datadict(self.data, self.files, html_name)
|
||||||
|
|
||||||
def _html_output(
|
|
||||||
self, normal_row, error_row, row_ender, help_text_html, errors_on_separate_row
|
|
||||||
):
|
|
||||||
"Output HTML. Used by as_table(), as_ul(), as_p()."
|
|
||||||
warnings.warn(
|
|
||||||
"django.forms.BaseForm._html_output() is deprecated. "
|
|
||||||
"Please use .render() and .get_context() instead.",
|
|
||||||
RemovedInDjango50Warning,
|
|
||||||
stacklevel=2,
|
|
||||||
)
|
|
||||||
# Errors that should be displayed above all fields.
|
|
||||||
top_errors = self.non_field_errors().copy()
|
|
||||||
output, hidden_fields = [], []
|
|
||||||
|
|
||||||
for name, bf in self._bound_items():
|
|
||||||
field = bf.field
|
|
||||||
html_class_attr = ""
|
|
||||||
bf_errors = self.error_class(bf.errors)
|
|
||||||
if bf.is_hidden:
|
|
||||||
if bf_errors:
|
|
||||||
top_errors.extend(
|
|
||||||
[
|
|
||||||
_("(Hidden field %(name)s) %(error)s")
|
|
||||||
% {"name": name, "error": str(e)}
|
|
||||||
for e in bf_errors
|
|
||||||
]
|
|
||||||
)
|
|
||||||
hidden_fields.append(str(bf))
|
|
||||||
else:
|
|
||||||
# Create a 'class="..."' attribute if the row should have any
|
|
||||||
# CSS classes applied.
|
|
||||||
css_classes = bf.css_classes()
|
|
||||||
if css_classes:
|
|
||||||
html_class_attr = ' class="%s"' % css_classes
|
|
||||||
|
|
||||||
if errors_on_separate_row and bf_errors:
|
|
||||||
output.append(error_row % str(bf_errors))
|
|
||||||
|
|
||||||
if bf.label:
|
|
||||||
label = conditional_escape(bf.label)
|
|
||||||
label = bf.label_tag(label) or ""
|
|
||||||
else:
|
|
||||||
label = ""
|
|
||||||
|
|
||||||
if field.help_text:
|
|
||||||
help_text = help_text_html % field.help_text
|
|
||||||
else:
|
|
||||||
help_text = ""
|
|
||||||
|
|
||||||
output.append(
|
|
||||||
normal_row
|
|
||||||
% {
|
|
||||||
"errors": bf_errors,
|
|
||||||
"label": label,
|
|
||||||
"field": bf,
|
|
||||||
"help_text": help_text,
|
|
||||||
"html_class_attr": html_class_attr,
|
|
||||||
"css_classes": css_classes,
|
|
||||||
"field_name": bf.html_name,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
if top_errors:
|
|
||||||
output.insert(0, error_row % top_errors)
|
|
||||||
|
|
||||||
if hidden_fields: # Insert any hidden fields in the last row.
|
|
||||||
str_hidden = "".join(hidden_fields)
|
|
||||||
if output:
|
|
||||||
last_row = output[-1]
|
|
||||||
# Chop off the trailing row_ender (e.g. '</td></tr>') 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": "",
|
|
||||||
"html_class_attr": html_class_attr,
|
|
||||||
"css_classes": "",
|
|
||||||
"field_name": "",
|
|
||||||
}
|
|
||||||
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
|
|
||||||
# hidden fields.
|
|
||||||
output.append(str_hidden)
|
|
||||||
return mark_safe("\n".join(output))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def template_name(self):
|
def template_name(self):
|
||||||
return self.renderer.form_template_name
|
return self.renderer.form_template_name
|
||||||
|
@ -297,6 +297,8 @@ to remove usage of these features.
|
|||||||
* The ``django.contrib.gis.admin.GeoModelAdmin`` and ``OSMGeoAdmin`` classes
|
* The ``django.contrib.gis.admin.GeoModelAdmin`` and ``OSMGeoAdmin`` classes
|
||||||
are removed.
|
are removed.
|
||||||
|
|
||||||
|
* The undocumented ``BaseForm._html_output()`` method is removed.
|
||||||
|
|
||||||
See :ref:`deprecated-features-4.1` for details on these changes, including how
|
See :ref:`deprecated-features-4.1` for details on these changes, including how
|
||||||
to remove usage of these features.
|
to remove usage of these features.
|
||||||
|
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
# RemovedInDjango50
|
# RemovedInDjango50
|
||||||
from django.forms import CharField, EmailField, Form, HiddenInput
|
from django.forms import CharField, EmailField, Form
|
||||||
from django.forms.utils import ErrorList
|
from django.forms.utils import ErrorList
|
||||||
from django.test import SimpleTestCase, ignore_warnings
|
from django.test import SimpleTestCase, ignore_warnings
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
from django.utils.deprecation import RemovedInDjango50Warning
|
||||||
|
|
||||||
from .test_forms import Person
|
|
||||||
|
|
||||||
|
|
||||||
class DivErrorList(ErrorList):
|
class DivErrorList(ErrorList):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
@ -20,21 +18,6 @@ class DivErrorList(ErrorList):
|
|||||||
|
|
||||||
|
|
||||||
class DeprecationTests(SimpleTestCase):
|
class DeprecationTests(SimpleTestCase):
|
||||||
def test_deprecation_warning_html_output(self):
|
|
||||||
msg = (
|
|
||||||
"django.forms.BaseForm._html_output() is deprecated. Please use "
|
|
||||||
".render() and .get_context() instead."
|
|
||||||
)
|
|
||||||
with self.assertRaisesMessage(RemovedInDjango50Warning, msg):
|
|
||||||
form = Person()
|
|
||||||
form._html_output(
|
|
||||||
normal_row='<p id="p_%(field_name)s"></p>',
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="</p>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_deprecation_warning_error_list(self):
|
def test_deprecation_warning_error_list(self):
|
||||||
class EmailForm(Form):
|
class EmailForm(Form):
|
||||||
email = EmailField()
|
email = EmailField()
|
||||||
@ -70,119 +53,3 @@ class DeprecatedTests(SimpleTestCase):
|
|||||||
'<div class="error">This field is required.</div></div>'
|
'<div class="error">This field is required.</div></div>'
|
||||||
'<p>Comment: <input type="text" name="comment" required></p>',
|
'<p>Comment: <input type="text" name="comment" required></p>',
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_field_name(self):
|
|
||||||
"""#5749 - `field_name` may be used as a key in _html_output()."""
|
|
||||||
|
|
||||||
class SomeForm(Form):
|
|
||||||
some_field = CharField()
|
|
||||||
|
|
||||||
def as_p(self):
|
|
||||||
return self._html_output(
|
|
||||||
normal_row='<p id="p_%(field_name)s"></p>',
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="</p>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
form = SomeForm()
|
|
||||||
self.assertHTMLEqual(form.as_p(), '<p id="p_some_field"></p>')
|
|
||||||
|
|
||||||
def test_field_without_css_classes(self):
|
|
||||||
"""
|
|
||||||
`css_classes` may be used as a key in _html_output() (empty classes).
|
|
||||||
"""
|
|
||||||
|
|
||||||
class SomeForm(Form):
|
|
||||||
some_field = CharField()
|
|
||||||
|
|
||||||
def as_p(self):
|
|
||||||
return self._html_output(
|
|
||||||
normal_row='<p class="%(css_classes)s"></p>',
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="</p>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
form = SomeForm()
|
|
||||||
self.assertHTMLEqual(form.as_p(), '<p class=""></p>')
|
|
||||||
|
|
||||||
def test_field_with_css_class(self):
|
|
||||||
"""
|
|
||||||
`css_classes` may be used as a key in _html_output() (class comes
|
|
||||||
from required_css_class in this case).
|
|
||||||
"""
|
|
||||||
|
|
||||||
class SomeForm(Form):
|
|
||||||
some_field = CharField()
|
|
||||||
required_css_class = "foo"
|
|
||||||
|
|
||||||
def as_p(self):
|
|
||||||
return self._html_output(
|
|
||||||
normal_row='<p class="%(css_classes)s"></p>',
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="</p>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
form = SomeForm()
|
|
||||||
self.assertHTMLEqual(form.as_p(), '<p class="foo"></p>')
|
|
||||||
|
|
||||||
def test_field_name_with_hidden_input(self):
|
|
||||||
"""
|
|
||||||
BaseForm._html_output() should merge all the hidden input fields and
|
|
||||||
put them in the last row.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class SomeForm(Form):
|
|
||||||
hidden1 = CharField(widget=HiddenInput)
|
|
||||||
custom = CharField()
|
|
||||||
hidden2 = CharField(widget=HiddenInput)
|
|
||||||
|
|
||||||
def as_p(self):
|
|
||||||
return self._html_output(
|
|
||||||
normal_row="<p%(html_class_attr)s>%(field)s %(field_name)s</p>",
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="</p>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
form = SomeForm()
|
|
||||||
self.assertHTMLEqual(
|
|
||||||
form.as_p(),
|
|
||||||
'<p><input id="id_custom" name="custom" type="text" required> custom'
|
|
||||||
'<input id="id_hidden1" name="hidden1" type="hidden">'
|
|
||||||
'<input id="id_hidden2" name="hidden2" type="hidden"></p>',
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_field_name_with_hidden_input_and_non_matching_row_ender(self):
|
|
||||||
"""
|
|
||||||
BaseForm._html_output() should merge all the hidden input fields and
|
|
||||||
put them in the last row ended with the specific row ender.
|
|
||||||
"""
|
|
||||||
|
|
||||||
class SomeForm(Form):
|
|
||||||
hidden1 = CharField(widget=HiddenInput)
|
|
||||||
custom = CharField()
|
|
||||||
hidden2 = CharField(widget=HiddenInput)
|
|
||||||
|
|
||||||
def as_p(self):
|
|
||||||
return self._html_output(
|
|
||||||
normal_row="<p%(html_class_attr)s>%(field)s %(field_name)s</p>",
|
|
||||||
error_row="%s",
|
|
||||||
row_ender="<hr><hr>",
|
|
||||||
help_text_html=" %s",
|
|
||||||
errors_on_separate_row=True,
|
|
||||||
)
|
|
||||||
|
|
||||||
form = SomeForm()
|
|
||||||
self.assertHTMLEqual(
|
|
||||||
form.as_p(),
|
|
||||||
'<p><input id="id_custom" name="custom" type="text" required> custom</p>\n'
|
|
||||||
'<input id="id_hidden1" name="hidden1" type="hidden">'
|
|
||||||
'<input id="id_hidden2" name="hidden2" type="hidden"><hr><hr>',
|
|
||||||
)
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user