From dcf2aaf1a10ad0789e9237067e34a96314f4a4f4 Mon Sep 17 00:00:00 2001 From: Daniel Sastre Date: Tue, 14 Mar 2017 14:09:25 +0100 Subject: [PATCH] Render the form in multiple columns --- CHANGES.txt | 6 ++- README.rst | 19 +++++++-- .../templates/bootstrapform/form.html | 20 ++++++++-- bootstrapform/templatetags/bootstrap.py | 40 +++++++++++++++---- docs/install.rst | 11 ++++- 5 files changed, 79 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 43df05b..aafa370 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,7 @@ +- 2017-03-13: + + - Add support to set the nº of columns + - 2015-03-09: - Fix unit test fail with Django 1.7 @nikolas @@ -15,7 +19,7 @@ - 2013-8-27: Add support for Bootstrap 3 - + contributed by `Nivl `_ diff --git a/README.rst b/README.rst index ac68d24..023d621 100644 --- a/README.rst +++ b/README.rst @@ -6,12 +6,12 @@ Django bootstrap form :alt: PyPI version :target: https://pypi.python.org/pypi/django-bootstrap-form -.. image:: https://travis-ci.org/tzangms/django-bootstrap-form.png?branch=master +.. image:: https://travis-ci.org/tzangms/django-bootstrap-form.png?branch=master :target: https://travis-ci.org/tzangms/django-bootstrap-form -.. image:: https://coveralls.io/repos/tzangms/django-bootstrap-form/badge.png?branch=master +.. image:: https://coveralls.io/repos/tzangms/django-bootstrap-form/badge.png?branch=master :target: https://coveralls.io/r/tzangms/django-bootstrap-form?branch=master - + Twitter Bootstrap for Django Form. @@ -38,6 +38,17 @@ Then to render your form:: +You can optionally set the nº of columns to layout the form:: + +
+ Form Title + {% csrf_token %} + {{ form|bootstrap:"3" }} +
+ +
+
+ You can also set class="form-vertical" on the form element. To use class="form-inline" on the form element, also change the "|boostrap" template tag to "|bootstrap_inline". @@ -59,4 +70,4 @@ It is also possible to create a horizontal form. The form class and template tag Demo ===== -Checkout this `Demo site `_ to see it in action. +Checkout this `Demo site `_ to see it in action. diff --git a/bootstrapform/templates/bootstrapform/form.html b/bootstrapform/templates/bootstrapform/form.html index d640e71..1a5995e 100644 --- a/bootstrapform/templates/bootstrapform/form.html +++ b/bootstrapform/templates/bootstrapform/form.html @@ -1,3 +1,5 @@ +{% load bootstrap %} + {% if form.non_field_errors %}
× @@ -11,6 +13,18 @@ {{ field }} {% endfor %} -{% for field in form.visible_fields %} - {% include 'bootstrapform/field.html' %} -{% endfor %} +{% if num_cols %} + {% for row in form|as_grid:num_cols %} +
+ {% for field in row %} +
+ {% include 'bootstrapform/field.html' %} +
+ {% endfor %} +
+ {% endfor %} +{% else %} + {% for field in form.visible_fields %} + {% include 'bootstrapform/field.html' %} + {% endfor %} +{% endif %} diff --git a/bootstrapform/templatetags/bootstrap.py b/bootstrapform/templatetags/bootstrap.py index c720db8..702d0c1 100644 --- a/bootstrapform/templatetags/bootstrap.py +++ b/bootstrapform/templatetags/bootstrap.py @@ -7,10 +7,11 @@ register = template.Library() + @register.filter -def bootstrap(element): +def bootstrap(element, num_cols=1): markup_classes = {'label': '', 'value': '', 'single_value': ''} - return render(element, markup_classes) + return render(element, markup_classes, int(num_cols)) @register.filter @@ -45,6 +46,7 @@ def bootstrap_horizontal(element, label_cols='col-sm-2 col-lg-2'): return render(element, markup_classes) + @register.filter def add_input_classes(field): if not is_checkbox(field) and not is_multiple_checkbox(field) \ @@ -54,7 +56,7 @@ def add_input_classes(field): field.field.widget.attrs['class'] = field_classes -def render(element, markup_classes): +def render(element, markup_classes, num_cols=None): element_type = element.__class__.__name__.lower() if element_type == 'boundfield': @@ -67,15 +69,23 @@ def render(element, markup_classes): for form in element.forms: for field in form.visible_fields(): add_input_classes(field) - template = get_template("bootstrapform/formset.html") - context = Context({'formset': element, 'classes': markup_classes}) + context = Context({ + 'formset': element, + 'classes': markup_classes, + 'col_width': num_cols and (config.BOOTSTRAP_COLUMN_COUNT // num_cols), + 'num_cols': num_cols, + }) else: for field in element.visible_fields(): add_input_classes(field) - template = get_template("bootstrapform/form.html") - context = Context({'form': element, 'classes': markup_classes}) + context = Context({ + 'form': element, + 'classes': markup_classes, + 'col_width': num_cols and (config.BOOTSTRAP_COLUMN_COUNT // num_cols), + 'num_cols': num_cols, + }) if django_version >= (1, 8): context = context.flatten() @@ -83,6 +93,22 @@ def render(element, markup_classes): return template.render(context) +@register.filter +def as_grid(form, num_cols=1): + visible_fields = form.visible_fields() + len_visible_fields = len(visible_fields) + rows = [] + columns = [] + + for i, field in enumerate(visible_fields, start=1): + columns.append(field) + if not i % num_cols or i == len_visible_fields: + rows.append(columns) + columns = [] + + return rows + + @register.filter def is_checkbox(field): return isinstance(field.field.widget, forms.CheckboxInput) diff --git a/docs/install.rst b/docs/install.rst index 0b62106..c0cc086 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -49,18 +49,25 @@ Usage {{ form|bootstrap }} - # or use with individual field + # Optionally set the nº of columns + {{ form|bootstrap:"3" }} + + # Or use with individual field {{ form.|bootstrap }} - To output individual fields # For horizontal forms {{ form|bootstrap_horizontal }} - + # Or with custom size (default is 'col-lg-2 col-sm-2') {{ form|bootstrap_horizontal:'col-lg-4' }} CHANGELOG --------- +- 2017-3-13: + + Add support to set the nº of columns + - 2013-8-27: Add support for Bootstrap 3, contributed by `Nivl `_