Skip to content

Instantly share code, notes, and snippets.

@shvets-sergey
Last active July 7, 2021 04:10
Show Gist options
  • Star 49 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save shvets-sergey/7394681 to your computer and use it in GitHub Desktop.
Save shvets-sergey/7394681 to your computer and use it in GitHub Desktop.
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 %}
@rawrgulmuffins
Copy link

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.

@shvets-sergey
Copy link
Author

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
Copy link

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
Copy link

zgoda commented Aug 8, 2014

The above macro renders CSRF hidden field twice.

@zgoda
Copy link

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
Copy link

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?

@philgyford
Copy link

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.

@troyleak
Copy link

@philgyford

Dropped an apostrophe, should be

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

Hope this saves someone some time.

@dumptyd
Copy link

dumptyd commented Apr 19, 2017

Thanks. 🙂

@zscholl
Copy link

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