Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Jinja2 macro to render bootstrap3 forms. Explanation is over here: http://bear-z.com/python/render-bootstrap-3-forms-with-wtforms-and-jinja/
{% extends 'base.html' %}
{% import 'macros.html' as macros %}
{% block content %}
<div class="row">
<div class="col-xs-12 col-md-3 col-sm-4 col-sm-offset-4 col-md-offset-4 col-lg-3 col-lg-offset-4">
<div class="login-message">
Login to AwesomeService!
</div>
{% call macros.render_form(form, action_url=url_for('login_view'), action_text='Login',
class_='login-form') %}
{{ macros.render_field(form.email, label_visible=false, placeholder='Email', type='email') }}
{{ macros.render_field(form.password, label_visible=false, placeholder='Password', type='password') }}
{{ macros.render_checkbox_field(form.remember_me) }}
{% endcall %}
</div>
</div>
{% endblock content %}
{# Renders field for bootstrap 3 standards.
Params:
field - WTForm field
kwargs - pass any arguments you want in order to put them into the html attributes.
There are few exceptions: for - for_, class - class_, class__ - class_
Example usage:
{{ macros.render_field(form.email, placeholder='Input email', type='email') }}
#}
{% macro render_field(field, label_visible=true) -%}
<div class="form-group {% if field.errors %}has-error{% endif %} {{ kwargs.pop('class_', '') }}">
{% if (field.type != 'HiddenField' and field.type !='CSRFTokenField') and label_visible %}
<label for="{{ field.id }}" class="control-label">{{ field.label }}</label>
{% endif %}
{{ field(class_='form-control', **kwargs) }}
{% if field.errors %}
{% for e in field.errors %}
<p class="help-block">{{ e }}</p>
{% endfor %}
{% endif %}
</div>
{%- endmacro %}
{# Renders checkbox fields since they are represented differently in bootstrap
Params:
field - WTForm field (there are no check, but you should put here only BooleanField.
kwargs - pass any arguments you want in order to put them into the html attributes.
There are few exceptions: for - for_, class - class_, class__ - class_
Example usage:
{{ macros.render_checkbox_field(form.remember_me) }}
#}
{% macro render_checkbox_field(field) -%}
<div class="checkbox">
<label>
{{ field(type='checkbox', **kwargs) }} {{ field.label }}
</label>
</div>
{%- endmacro %}
{# Renders radio field
Params:
field - WTForm field (there are no check, but you should put here only BooleanField.
kwargs - pass any arguments you want in order to put them into the html attributes.
There are few exceptions: for - for_, class - class_, class__ - class_
Example usage:
{{ macros.render_radio_field(form.answers) }}
#}
{% macro render_radio_field(field) -%}
{% for value, label, _ in field.iter_choices() %}
<div class="radio">
<label>
<input type="radio" name="{{ field.id }}" id="{{ field.id }}" value="{{ value }}">{{ label }}
</label>
</div>
{% endfor %}
{%- endmacro %}
{# Renders WTForm in bootstrap way. There are two ways to call function:
- as macros: it will render all field forms using cycle to iterate over them
- as call: it will insert form fields as you specify:
e.g. {% call macros.render_form(form, action_url=url_for('login_view'), action_text='Login',
class_='login-form') %}
{{ macros.render_field(form.email, placeholder='Input email', type='email') }}
{{ macros.render_field(form.password, placeholder='Input password', type='password') }}
{{ macros.render_checkbox_field(form.remember_me, type='checkbox') }}
{% endcall %}
Params:
form - WTForm class
action_url - url where to submit this form
action_text - text of submit button
class_ - sets a class for form
#}
{% macro render_form(form, action_url='', action_text='Submit', class_='', btn_class='btn btn-default') -%}
<form method="POST" action="{{ action_url }}" role="form" class="{{ class_ }}">
{{ form.hidden_tag() if form.hidden_tag }}
{% if caller %}
{{ caller() }}
{% else %}
{% for f in form %}
{% if f.type == 'BooleanField' %}
{{ render_checkbox_field(f) }}
{% elif f.type == 'RadioField' %}
{{ render_radio_field(f) }}
{% else %}
{{ render_field(f) }}
{% endif %}
{% endfor %}
{% endif %}
<button type="submit" class="{{ btn_class }}">{{ action_text }} </button>
</form>
{%- endmacro %}
{% extends 'base.html' %}
{% from 'macros.html' import render_form %}
{% block content %}
<div class="your-form">
{{ render_form(your_form, action_url='/submit_url', action_text='Submit Form') }}
</div>
{% endblock content %}

Hello bearz. I had to change line 15 to say

    {% if field.type != 'CSRFTokenField' and label_visible %}

with the latest version of wtforms. Just wanted to give you a heads up.

Owner

bearz commented Jan 21, 2014

Thank you, Alex! I put 'or' to there since there can be CSRFToken field (for security reasons) and as well as hidden field (e.g. for passing some id to edit form).

P.S. don't know how I missed your comment for such a long time (

piranha commented Mar 29, 2014

@bearz it should be 'and' instead of 'or' there I believe. :) If not hidden, not csrf, and label_visible - then display a label.

zgoda commented Aug 8, 2014

The above macro renders CSRF hidden field twice.

zgoda commented Aug 8, 2014

Line 15 causes the label tag to be rendered 2 times, label text is emitted with field.label.text while field.label emits also html tags.

dhiraka commented Apr 29, 2015

I tried to write code for drop down menu but failed. Could you please share the code for drop down type as well?

To prevent the hidden fields being rendered twice when using the render_form() macro, I changed line 90 from:

{% else %}

to:

{% elif f.type != 'CSRFTokenField' and f.type != 'HiddenField %}

The tokens are already output by the form.hidden_tag() part on line 81.

@philgyford

Dropped an apostrophe, should be

{% elif f.type != 'CSRFTokenField' and f.type != 'HiddenField' %}

Hope this saves someone some time.

dumptyd commented Apr 19, 2017

Thanks. 🙂

zscholl commented Aug 22, 2017

Thanks for the macros! Saved me a bunch of work :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment