Bootstrap-Flask

Bootstrap 4 helper for Flask/Jinja2.

Contents

Basic Usage

Installation

$ pip install bootstrap-flask

This project can’t work with Flask-Bootstrap at the same time. If you have already installed Flask-Bootstrap in the same Python enviroment, you have to uninstall it and then reinstall this project:

$ pip uninstall flask-bootstrap bootstrap-flask
$ pip install bootstrap-flask

Tip

See Migrate from Flask-Bootstrap to learn how to migrate from Flask-Bootstrap.

Initialization

from flask_bootstrap import Bootstrap
from flask import Flask

app = Flask(__name__)

bootstrap = Bootstrap(app)

Resources helpers

Bootstrap-Flask provides two helper functions to load Bootstrap resources in the template: bootstrap.load_css() and bootstrap.load_js().

Call it in your base template, for example:

<head>
....
{{ bootstrap.load_css() }}
</head>
<body>
...
{{ bootstrap.load_js() }}
</body>

You can pass version to pin the Bootstrap 4 version you want to use. It defaults to load files from CDN. Set BOOTSTRAP_SERVE_LOCAL to True to use built-in local files. However, these methods are optional, you can also write <href></href> and <script></script> tags to include Bootstrap resources (from your static folder or CDN) manually by yourself.

Starter template

For reasons of flexibility, Bootstrap-Flask doesn’t include built-in base templates (this may change in the future). For now, you have to create a base template yourself. Be sure to use an HTML5 doctype and include a viewport meta tag for proper responsive behaviors. Here’s an example base template:

<!doctype html>
<html lang="en">
    <head>
        {% block head %}
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        {% block styles %}
            <!-- Bootstrap CSS -->
            {{ bootstrap.load_css() }}
        {% endblock %}

        <title>Your page title</title>
        {% endblock %}
    </head>
    <body>
        <!-- Your page content -->
        {% block content %}{% endblock %}

        {% block scripts %}
            <!-- Optional JavaScript -->
            {{ bootstrap.load_js() }}
        {% endblock %}
    </body>
</html>

Use this in your templates folder (suggested names are base.html or layout.html etc.), and inherit it in child templates. See Template Inheritance for more details on inheritance.

Macros

Macro Templates Path Description
render_field() bootstrap/form.html Render a WTForms form field
render_form() bootstrap/form.html Render a WTForms form
render_pager() bootstrap/pagination.html Render a basic Flask-SQLAlchemy pagniantion
render_pagination() bootstrap/pagination.html Render a standard Flask-SQLAlchemy pagination
render_nav_item() bootstrap/nav.html Render a navigation item
render_breadcrumb_item() bootstrap/nav.html Render a breadcrumb item
render_static() bootstrap/utils.html Render a resource reference code (i.e. <link>, <script>)
render_messages() bootstrap/utils.html Render flashed messages send by flash() fucntion
render_table() bootstrap/table.html Render a table with given data

How to use these macros? It’s quite simple, just import them from the corresponding path and call them like any other macro:

{% from 'bootstrap/form.html' import render_form %}

{{ render_form(form) }}

Go to the Use Macros page to see the detailed usage for these macros.

Configurations

Configuration Variable Default Value Description
BOOTSTRAP_SERVE_LOCAL False If set to True, local resources will be used for load_* methods.
BOOTSTRAP_BTN_STYLE 'secondary' Default form button style, will change to primary in next major release
BOOTSTRAP_BTN_SIZE 'md' Default form button size

Tip

See Form Button Customization to learn how to customize form buttons.

Use Macros

These macros will help you to generate Bootstrap-markup codes quickly and easily.

render_nav_item()

Render a Bootstrap nav item.

Example
{% from 'bootstrap/nav.html' import render_nav_item %}

<nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="navbar-nav mr-auto">
        {{ render_nav_item('index', 'Home') }}
        {{ render_nav_item('explore', 'Explore') }}
        {{ render_nav_item('about', 'About') }}
    </div>
</nav>
API
render_nav_item(endpoint, text, badge='', use_li=False, **kwargs)

Render a Bootstrap nav item.

Parameters:
  • endpoint – The endpoint used to generate URL.
  • text – The text that will displayed on the item.
  • badge – Badge text.
  • use_li – Default to generate <a></a>, if set to True, it will generate <li><a></a></li>.
  • kwargs – Additional keyword arguments pass to url_for().

render_breadcrumb_item()

Render a Bootstrap breadcrumb item.

Example
{% from 'bootstrap/nav.html' import render_breadcrumb_item %}

<nav aria-label="breadcrumb">
    <ol class="breadcrumb">
        {{ render_breadcrumb_item('home', 'Home') }}
        {{ render_breadcrumb_item('users', 'Users') }}
        {{ render_breadcrumb_item('posts', 'Posts') }}
        {{ render_breadcrumb_item('comments', 'Comments') }}
    </ol>
</nav>
API
render_breadcrumb_item(endpoint, text, **kwargs)

Render a Bootstrap breadcrumb item.

Parameters:
  • endpoint – The endpoint used to generate URL.
  • text – The text that will displayed on the item.
  • kwargs – Additional keyword arguments pass to url_for().

render_field()

Render a form field create by Flask-WTF/WTForms.

Example
{% from 'bootstrap/form.html' import render_field %}

<form method="post">
    {{ form.csrf_token() }}
    {{ render_field(form.username) }}
    {{ render_field(form.password) }}
    {{ render_field(form.submit) }}
</form>
API
render_field(field, form_type="basic", horizontal_columns=('lg', 2, 10), button_style="", button_size="", button_map={})

Render a single form field.

Parameters:
  • field – The form field (attribute) to render.
  • form_type – One of basic, inline or horizontal. See the Bootstrap docs for details on different form layouts.
  • horizontal_columns – When using the horizontal layout, layout forms like this. Must be a 3-tuple of (column-type, left-column-size, right-column-size).
  • button_style – Accpet Bootstrap button style name (i.e. priamry, secondary, outline-success, etc.), default to secondary (e.g. btn-secondary). This will overwrite config BOOTSTRAP_BTN_STYLE.
  • button_size – Accept Bootstrap button size name: sm, md, lg, block, default to md. This will overwrite config BOOTSTRAP_BTN_SIZE.
  • button_map – A dictionary, mapping button field name to Bootstrap button style names. For example, {'submit': 'success'}. This will overwrite button_style and BOOTSTRAP_BTN_STYLE.

Tip

See button_customization to learn how to customize form buttons.

render_form()

Render a form object create by Flask-WTF/WTForms.

Example
{% from 'bootstrap/form.html' import render_form %}

{{ render_form(form) }}
API
render_form(form, action="", method="post", extra_classes=None, role="form", form_type="basic", horizontal_columns=('lg', 2, 10), enctype=None, button_style="", button_size="", button_map={}, id="", novalidate=False, render_kw={})

Outputs Bootstrap-markup for a complete Flask-WTF form.

Parameters:
  • form – The form to output.
  • action – The URL to receive form data.
  • method<form> method attribute.
  • extra_classes – The classes to add to the <form>.
  • role<form> role attribute.
  • form_type – One of basic, inline or horizontal. See the Bootstrap docs for details on different form layouts.
  • horizontal_columns – When using the horizontal layout, layout forms like this. Must be a 3-tuple of (column-type, left-column-size, right-column-size).
  • enctype<form> enctype attribute. If None, will automatically be set to multipart/form-data if a FileField or MultipleFileField is present in the form.
  • button_style – Accpet Bootstrap button style name (i.e. priamry, secondary, outline-success, etc.), default to secondary (e.g. btn-secondary). This will overwrite config BOOTSTRAP_BTN_STYLE.
  • button_size – Accept Bootstrap button size name: sm, md, lg, block, default to md. This will overwrite config BOOTSTRAP_BTN_SIZE.
  • button_map – A dictionary, mapping button field name to Bootstrap button style names. For example, {'submit': 'success'}. This will overwrite button_style and BOOTSTRAP_BTN_STYLE.
  • id – The <form> id attribute.
  • novalidate – Flag that decide whether add novalidate class in <form>.
  • render_kw – A dictionary, specifying custom attributes for the <form> tag.
form_errors(form, hiddens=True)

Renders paragraphs containing form error messages. This is usually only used to output hidden field form errors, as others are attached to the form fields.

Parameters:
  • form – Form whose errors should be rendered.
  • hiddens – If True, render errors of hidden fields as well. If 'only', render only these.

Tip

See Form Button Customization to learn how to customize form buttons.

render_form_row()

Render a row of a grid form.

Example
{% from 'bootstrap/form.html' import render_form_row %}

<form method="post">
    {{ form.csrf_token() }}
    {{ render_form_row([form.username, form.password]) }}
    {{ render_form_row([form.remember]) }}
    {{ render_form_row([form.submit]) }}
    {# Custom col which should use class col-md-2, and the others the defaults: #}
    {{ render_form_row([form.title, form.first_name, form.surname], col_map={'title': 'col-md-2'}) }}
    {# Custom col which should use class col-md-2 and modified col class for the default of the other fields: #}
    {{ render_form_row([form.title, form.first_name, form.surname], col_class_default='col-md-5', col_map={'title': 'col-md-2'}) }}
</form>
API
render_form_row(fields, row_class='form-row', col_class_default='col', col_map={}, button_style="", button_size="", button_map={})

Render a bootstrap row with the given fields.

Parameters:
  • fields – An iterable of fields to render in a row.
  • row_class – Class to apply to the div intended to represent the row, like form-row or row
  • col_class_default – The default class to apply to the div that represents a column if nothing more specific is said for the div column of the rendered field.
  • col_map – A dictionary, mapping field.name to a class definition that should be applied to the div column that contains the field. For example: col_map={'username': 'col-md-2'})
  • button_style – Accpet Bootstrap button style name (i.e. priamry, secondary, outline-success, etc.), default to secondary (e.g. btn-secondary). This will overwrite config BOOTSTRAP_BTN_STYLE.
  • button_size – Accept Bootstrap button size name: sm, md, lg, block, default to md. This will overwrite config BOOTSTRAP_BTN_SIZE.
  • button_map – A dictionary, mapping button field name to Bootstrap button style names. For example, {'submit': 'success'}. This will overwrite button_style and BOOTSTRAP_BTN_STYLE.

Tip

See Form Button Customization to learn how to customize form buttons.

render_pager()

Render a pagination object create by Flask-SQLAlchemy.

Example
{% from 'bootstrap/pagination.html' import render_pager %}

{{ render_pager(pagination) }}
API
render_pager(pagination, fragment='', prev=('<span aria-hidden="true">&larr;</span> Previous')|safe, next=('Next <span aria-hidden="true">&rarr;</span>')|safe, align='', **kwargs)

Renders a simple pager for query pagination.

Parameters:
  • paginationPagination instance.
  • fragment – Add url fragment into link, such as #comment.
  • prev – Symbol/text to use for the “previous page” button.
  • next – Symbol/text to use for the “next page” button.
  • align – Can be ‘left’, ‘center’ or ‘right’, default to ‘left’.
  • kwargs – Additional arguments passed to url_for.

render_pagination()

Render a pagination object create by Flask-SQLAlchemy.

Example
{% from 'bootstrap/pagination.html' import render_pagination %}

{{ render_pagination(pagination) }}
API
render_pagination(pagination, endpoint=None, prev='«', next='»', ellipses='…', size=None, args={}, fragment='', align='', **kwargs)

Render a standard pagination for query pagination.

Parameters:
  • paginationPagination instance.
  • endpoint – Which endpoint to call when a page number is clicked. url_for() will be called with the given endpoint and a single parameter, page. If None, uses the requests current endpoint.
  • prev – Symbol/text to use for the “previous page” button. If None, the button will be hidden.
  • next – Symbol/text to use for the “next page” button. If None, the button will be hidden.
  • ellipses – Symbol/text to use to indicate that pages have been skipped. If None, no indicator will be printed.
  • size – Can be ‘sm’ or ‘lg’ for smaller/larger pagination.
  • args – Additional arguments passed to url_for(). If endpoint is None, uses args and view_args
  • fragment – Add url fragment into link, such as #comment.
  • align – The align of the paginationi. Can be ‘left’, ‘center’ or ‘right’, default to ‘left’.
  • kwargs – Extra attributes for the <ul>-element.

render_static()

Render a resource reference code (i.e. <link>, <script>).

Example
{% from 'bootstrap/utils.html' import render_static %}

{{ render_static('css', 'style.css') }}
API
render_static(type, filename_or_url, local=True)

Render a resource reference code (i.e. <link>, <script>).

Parameters:
  • type – Resources type, one of css, js, icon.
  • filename_or_url – The name of the file, or the full url when local set to False.
  • local – Load local resources or from the passed URL.

render_messages()

Render flashed messages send by flask.flash().

Example

Flash the message in your view function with flash(message, category):

from flask import flash

@app.route('/test')
def test():
    flash('a info message', 'info')
    flash('a danger message', 'danger')
    return your_template

Render the messages in your base template (normally below the navbar):

{% from 'bootstrap/utils.html' import render_messages %}

<nav>...</nav>
{{ render_messages() }}
<main>...</main>
API
render_messages(messages=None, container=False, transform={...}, default_category='primary', dismissible=False, dismiss_animate=False)

Render Bootstrap alerts for flash messages send by flask.flash().

Parameters:
  • messages – The messages to show. If not given, default to get from flask.get_flashed_messages(with_categories=True).
  • container – If true, will output a complete <div class="container"> element, otherwise just the messages each wrapped in a <div>.
  • transform – A dictionary of mappings for categories. Will be looked up case-insensitively. Default maps all Python loglevel names to Bootstrap CSS classes.
  • default_category – If a category does not has a mapping in transform, it is passed through unchanged. default_category will be used when category is empty.
  • dismissible – If true, will output a button to close an alert. For fully functioning dismissible alerts, you must use the alerts JavaScript plugin.
  • dismiss_animate – If true, will enable dismiss animate when click the dismiss button.

When you call flash('message', 'category'), threre are 8 category options available, mapping to Bootstrap 4’s alerts type:

primary, secondary, success, danger, warning, info, light, dark.

If you want to use HTML in your message body, just warpper your message string with flask.Markup to tell Jinja it’s safe:

from flask import flash, Markup

@app.route('/test')
def test():
    flash(Markup('a info message with a link: <a href="/">Click me!</a>'), 'info')
    return your_template

render_table()

Render a Bootstrap table.

Example
{% from 'bootstrap/table.html' import render_table %}

{{ render_table(data) }}
API
render_table(data, titles=None, primary_key='id', primary_key_title='#', caption=None, table_classes=None, header_classes=None, responsive=False, responsive_class='table-responsive')

Render a Bootstrap table.

Parameters:
  • data – An iterable of data objects to render. Can be dicts or class objects.
  • titles – An iterable of tuples of the format (prop, label) e.g [('id', '#')], if not provided, will automatically detect on provided data, currently only support SQLAlchemy object.
  • primary_key – Primary key identifier for a single row, default to id.
  • primary_key_title – Primary key title for a single row, default to #.
  • caption – A caption to attach to the table.
  • table_classes – A string of classes to apply to the table (e.g 'table-small table-dark').
  • header_classes – A string of classes to apply to the table header (e.g 'thead-dark').
  • responsive – Whether to enable/disable table responsiveness.
  • responsive_class – The responsive class to apply to the table. Default is 'table-responsive'.

Migrate from Flask-Bootstrap

If you come from Flask-Bootstrap, looking for an alternative that supports Bootstrap 4, well, then you are in the right palce.

Bootstrap-Flask was origined as a fork of Flask-Bootstrap, but some APIs were changed, deleted and improved, some bugs were fixed, and on top of all that, some new macros were added. This tutorial will go through all the steps to migrate from Flask-Bootstrap.

Uninstall and Install

Flask-Bootstrap and Bootstrap-Flask can’t live together, so you have to uninstall Flask-Bootstrap first and then install Bootstra-Flask:

$ pip uninstall flask-bootstrap
$ pip install bootstrap-flask

if you accidently installed both of them, you will need to uninstall them both first:

$ pip uninstall flask-bootstrap bootstrap-flask
$ pip install bootstrap-flask

If you want to use both Flask-Bootstrap and Bootstrap-Flask for different projects, you can use virtual enviroment.

Initialize the Extension

The initialization of this extension is the same as with Flask-Bootstrap. The package’s name is still flask_bootstrap, in order to follow the rule of Flask extension development and easy the pain of migration.

from flask_bootstrap import Bootstrap
from flask import Flask

app = Flask(__name__)

bootstrap = Bootstrap(app)

Create Base Template

In Flask-Bootstrap, there is a built-in base template called bootstrap/base.html. This extension does not provide one. You have to create it by yourself; an example starter is given here:

<!doctype html>
<html lang="en">
    <head>
        {% block head %}
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

        {% block styles %}
            <!-- Bootstrap CSS -->
            {{ bootstrap.load_css() }}
        {% endblock %}

        <title>Your page title</title>
        {% endblock %}
    </head>
    <body>
        <!-- Your page content -->
        {% block content %}{% endblock %}

        {% block scripts %}
            <!-- Optional JavaScript -->
            {{ bootstrap.load_js() }}
        {% endblock %}
    </body>
</html>

Just create a file called base.html inside your templates folder, copy the contents above into it. There are two resource helper methods used in the example template above (i.e. bootstrap.load_css() and bootstrap.load_js()). They will generate <href></href> and <script></script> codes to include Bootstrap’s CSS and JavaScript files. These default to load the resources from CDN (provided by jsDelivr). If you set the configuration variable BOOTSTRAP_SERVE_LOCAL to True the local resources inside the package folder will be used instead.

It’s optional to use these resources methods, you can write the codes by yourself to load Boostrap resources in your application’s static folder, or from a different CDN provider that you want to use.

Change Template and Macro Name

The template bootstrap/wtf.html changed to bootstrap/form.html, some macro’s name was changed too:

For example, you will need to change the import statement:

{% from 'bootstrap/wtf.html' import quick_form, form_field %}

to:

{% from 'bootstrap/form.html' import render_form, render_field %}

The macros below were removed (or not supported yet):

  • ie8()
  • icon()
  • form_button()
  • analytics()
  • uanalytics()

There are also some new macros were introduced, check them out at Macros section.

Advanced Usage

Form Button Customization

Button Style

When you use form related macros, you have a couple ways to style buttons. Before we start to dive into the solutions, let’s review some Bootstrap basics: In Bootstrap 4, you have 9 normal button style and 8 outline button style, so you have 17 button style classes below:

  • btn-primary
  • btn-secondary
  • btn-success
  • btn-danger
  • btn-warning
  • btn-info
  • btn-light
  • btn-dark
  • btn-link
  • btn-outline-primary
  • btn-outline-secondary
  • btn-outline-success
  • btn-outline-danger
  • btn-outline-warning
  • btn-outline-info
  • btn-outline-light
  • btn-outline-dark

Remove the btn- prefix, you will get what we (actually, I) called “Bootstrap button style name”:

  • primary
  • secondary
  • success
  • danger
  • warning
  • info
  • light
  • dark
  • link
  • outline-primary
  • outline-secondary
  • outline-success
  • outline-danger
  • outline-warning
  • outline-info
  • outline-light
  • outline-dark

You will use these names in Bootstrap-Flask. First, you configuration variables BOOTSTRAP_BTN_STYLE to set a global form button style:

from flask import Flask
from flask_bootstrap import Bootstrap

app = Flask(__name__)
bootstrap = Bootstrap(app)

app.config['BOOTSTRAP_BTN_STYLE'] = 'primary'  # default to 'secondary'

Or you can use button_style parameter when using render_form, render_field and render_form_row, this parameter will overwrite BOOTSTRAP_BTN_STYLE:

{% from 'bootstrap/form.html' import render_form %}

{{ render_form(form, button_style='success') }}

Smirily, you can use this way to control the button size. In Bootstrap 4, buttons can have 4 sizes:

  • btn-sm
  • btn-md (the default size)
  • btn-lg
  • btn-block

So, the size names used in Bootstrap-Flask will be:

  • sm
  • md (the default size)
  • lg
  • block

Now you can use a configuration variable called BOOTSTRAP_BTN_STYLE to set global form button size:

from flask import Flask
from flask_bootstrap import Bootstrap

app = Flask(__name__)
bootstrap = Bootstrap(app)

app.config['BOOTSTRAP_BTN_SIZE'] = 'sm'  # default to 'md'

there also a parameter called button_size in form related macros (it will overwrite BOOTSTRAP_BTN_SIZE):

{% from 'bootstrap/form.html' import render_form %}

{{ render_form(form, button_size='lg') }}

if you need a block level small button (btn btn-sm btn-block), you can just do something hacky like this:

app.config['BOOTSTRAP_BTN_SIZE'] = 'sm btn-block'

What if I have three buttons in one form, and I want they have different styles and sizes? The answer is button_map parameter in form related macros. button_map is a dictionary that mapping button field name to Bootstrap button style names. For example, {'submit': 'success'}. Here is a more complicate example:

{% from 'bootstrap/form.html' import render_form %}

{{ render_form(form, {'submit': 'success', 'cancel': 'secondary', 'delete': 'danger'}) }}

It will overwrite button_style and BOOTSTRAP_BTN_STYLE.

Run the demo application

Type these commands in the terminal:

$ git clone https://github.com/greyli/bootstrap-flask.git
$ cd bootstrap-flask/examples
$ pip install -r requirements.txt
$ flask run

Now go to http://localhost:5000.

API Reference

If you are looking for information on a specific function, class or method, this part of the documentation is for you.

API Reference

class flask_bootstrap.Bootstrap(app=None)
init_app(app)
static load_css(version='4.3.1')

Load Bootstrap’s css resources with given version.

New in version 0.1.0.

Parameters:version – The version of Bootstrap.
static load_js(version='4.3.1', jquery_version='3.4.1', popper_version='1.14.0', with_jquery=True, with_popper=True)

Load Bootstrap and related library’s js resources with given version.

New in version 0.1.0.

Parameters:
  • version – The version of Bootstrap.
  • jquery_version – The version of jQuery.
  • popper_version – The version of Popper.js.
  • with_jquery – Include jQuery or not.
  • with_popper – Include Popper.js or not.

Changelog

Changelog

1.4

Release data: 6/15

  • Add render_table macro to render a Bootstrap table (#71)

1.3.2

Release data: 2020/5/30

  • Support display error message for RadioField and BooleanField, display description for RadioField.

1.3.1

Release data: 2020/4/29

  • Fix add field.render_kw.class to form label class attribute.
  • Fix append extra space in class attribute when no field.render_kw.class presents (#63).

1.3.0

Release date: 2020/4/23

1.2.0

Release date: 2019/12/5

  • Add macro render_messages for rendering flashed messages.
  • Fix rendering bug for WTForms FormField (#34).

1.1.0

Release date: 2019/9/9

  • Update Bootstrap version to 4.3.1

1.0.10

Release date: 2019/3/7

  • Added macro render_form_row for rendering a row of a bootstrap grid form.

1.0.9

Release date: 2018/11/14

  • Fix missing error message when form type was horizontal.
  • Fix missing input label for RadioField.
  • Fix RadioField grid when form type was horizontal.

1.0.8

Release date: 2018/9/6

  • Correct macro name used in templates/boostrap/form.html: form_field –> render_field.

1.0.7

Release date: 2018/8/30

  • Built-in resources loading not based on``FLASK_ENV``.

1.0.6

Release date: 2018/8/7

  • Fix unmatched built-in jQuery filename. (#8)

1.0.5

Release date: 2018/8/7

  • Fix KeyError Exception if ENV isn’t defined. (#7)

1.0.4

Release date: 2018/7/24

  • Add missing <script> tag in resources URL. (#3)

1.0.3

Release date: 2018/7/22

  • Built-in resources will be used when FLASK_ENV set to development.
  • Change CDN provider to jsDelivr.

1.0.2

Release date: 2018/7/21

  • Include popper.js before bootstrap.js in bootstrap.load_js(). (#2)

1.0.1

Release date: 2018/7/1

  • Fix local resources path error
  • Add basic unit tests

1.0

Release date: 2018/6/11

Initialize release.

Development

We welcome all kinds of contributions. You can run test like this:

$ python setup.py test

Authors

Maintainer: Grey Li

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License (see the LICENSE file for details).

Some macros were part of Flask-Bootstrap and were modified under the terms of its BSD License.