{% for field in hidden_fields %}{{ field }}{% endfor %}
+{% endif %}
+{% for field, errors in fields %}
+
+ {% if field.use_fieldset %}
+ {% endif %}
+ {% if loop.last %}
+ {% for field in hidden_fields %}{{ field }}{% endfor %}
+ {% endif %}
+
+{% endfor %}
+{% if not fields and not errors %}
+ {% for field in hidden_fields %}{{ field }}{% endfor %}
+{% endif %}
diff --git a/django/forms/jinja2/django/forms/formsets/div.html b/django/forms/jinja2/django/forms/formsets/div.html
new file mode 100644
index 0000000000..0dda779d3f
--- /dev/null
+++ b/django/forms/jinja2/django/forms/formsets/div.html
@@ -0,0 +1 @@
+{{ formset.management_form }}{% for form in formset %}{{ form.as_div() }}{% endfor %}
diff --git a/django/forms/templates/django/forms/div.html b/django/forms/templates/django/forms/div.html
new file mode 100644
index 0000000000..0328fdf8d3
--- /dev/null
+++ b/django/forms/templates/django/forms/div.html
@@ -0,0 +1,24 @@
+{{ errors }}
+{% if errors and not fields %}
+
{% for field in hidden_fields %}{{ field }}{% endfor %}
+{% endif %}
+{% for field, errors in fields %}
+
+ {% if field.use_fieldset %}
+ {% endif %}
+ {% if forloop.last %}
+ {% for field in hidden_fields %}{{ field }}{% endfor %}
+ {% endif %}
+
+{% endfor %}
+{% if not fields and not errors %}
+ {% for field in hidden_fields %}{{ field }}{% endfor %}
+{% endif %}
diff --git a/django/forms/templates/django/forms/formsets/div.html b/django/forms/templates/django/forms/formsets/div.html
new file mode 100644
index 0000000000..93499897d4
--- /dev/null
+++ b/django/forms/templates/django/forms/formsets/div.html
@@ -0,0 +1 @@
+{{ formset.management_form }}{% for form in formset %}{{ form.as_div }}{% endfor %}
diff --git a/django/forms/utils.py b/django/forms/utils.py
index 7d3bb5ad48..77678054db 100644
--- a/django/forms/utils.py
+++ b/django/forms/utils.py
@@ -73,6 +73,10 @@ class RenderableFormMixin(RenderableMixin):
"""Render as
elements excluding the surrounding
tag."""
return self.render(self.template_name_ul)
+ def as_div(self):
+ """Render as
elements."""
+ return self.render(self.template_name_div)
+
class RenderableErrorMixin(RenderableMixin):
def as_json(self, escape_html=False):
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index 8530af2611..72937bfa9a 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -607,6 +607,55 @@ list using ``{{ form.as_ul }}``.
Each helper pairs a form method with an attribute giving the appropriate
template name.
+``as_div()``
+~~~~~~~~~~~~
+
+.. attribute:: Form.template_name_div
+
+.. versionadded:: 4.1
+
+The template used by ``as_div()``. Default: ``'django/forms/div.html'``.
+
+.. method:: Form.as_div()
+
+.. versionadded:: 4.1
+
+``as_div()`` renders the form as a series of ``
`` elements, with each
+``
`` containing one field, such as:
+
+.. code-block:: pycon
+
+ >>> f = ContactForm()
+ >>> f.as_div()
+
+… gives HTML like:
+
+.. code-block:: html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+.. note::
+
+ Of the framework provided templates and output styles, ``as_div()`` is
+ recommended over the ``as_p()``, ``as_table()``, and ``as_ul()`` versions
+ as the template implements ``