Skip to main content

Simple library for rendering WTForms in HTML as Bootstrap 5 form controls

Project description

wtforms-bootstrap5

Simple library for rendering WTForms in HTML as Bootstrap 5 form controls

Notice: this project is still in very early stage, the API may change a lots rapidly

Features

  • MIT licensed - it doesn't infect your code
  • Light weight - not much code and little dependencies
  • Latest Bootstrap 5 - generates forms in latest Bootstrap 5 style
  • High customizable - you can generate different kind of Bootstrap 5 form controls and layouts
  • Template engine friendly - chained method calls making it easy to integrate with template engine
  • Covered with automatic tests - yep, we have test cases

Why?

Everytime I build a website with WTForms, I spend way too much time in writing HTML and Jinja template for rendering a form as Bootstrap 5 form controls. Work smart is an important value we have here at Launch Platform, so I wonder why not make a library for making rendering Bootstrap 5 style WTForms controls easily? So here you go, wtforms-bootstrap5 is created, open sourced under MIT license. It's a simple Python library for rendering WTForms in Bootstrap 5 favor.

Install

To install the formatter, simply run

pip install wtforms-bootstrap5

Example

First, you define your form as you would usually do with WTForms:

from wtforms import Form
from wtforms import EmailField
from wtforms import PasswordField
from wtforms import SelectField
from wtforms import BooleanField
from wtforms import SubmitField


class MyForm(Form):
    email = EmailField("Email", render_kw=dict(placeholder="Foobar"))
    password = PasswordField("Password", description="Your super secret password")
    city = SelectField("City", choices=["Los Angle", "San Francisco", "New York"])
    agree_terms = BooleanField("I agrees to terms and service")
    submit = SubmitField()

Then you can use RenderContext for rendering your form like this

from wtforms_bootstrap5 import RendererContext

form = MyForm()
context = RendererContext()
html = context.render(form)

The form will be rendered as HTML like

<form method="POST"><div class="mb-3"><label class="form-label" for="email">Email</label><input class="form-control" id="email" name="email" type="email" value=""></div>
<div class="mb-3"><label class="form-label" for="password">Password</label><input class="form-control" id="password" name="password" type="password" value=""><div class="form-text">Your super secret password</div></div>
<div class="mb-3"><label class="form-label" for="city">City</label><select class="form-select" id="city" name="city"><option value="Los Angle">Los Angle</option><option value="San Francisco">San Francisco</option><option value="New York">New York</option></select></div>
<div class="mb-3"><div class="form-check"><label class="form-check-label" for="agree_terms">I agrees to terms and service</label><input class="form-check-input" id="agree_terms" name="agree_terms" type="checkbox" value="y"></div></div>
<div class="mb-3"><input class="btn btn-primary" id="submit" name="submit" type="submit" value="Submit"></div></form>

And it will look like this

Form rendered in Bootstrap 5 favor

By default, a sensible simple layout style will be used.

Customize the form

There are many similar open source libraries out there, but most of them are very hard to customize. Once you adopt it, then you can only render your form in a specific style. As a result, I found myself writing HTML manually without using the library to save time.

To avoid the same mistake, we want to make wtforms-bootstrap5 very easy to customize without compromising too much of its reusability. Here's an example how you can turn the example above into a column based form.

html = (
    renderer_context
    .form(action="/sign-up")
    .default_field(
        row_class="row mb-3",
        label_class="form-label col-2",
        field_wrapper_class="col-10",
        field_wrapper_enabled=True,
    )
    .field(
        "agree_terms",
        wrapper_class="offset-2",
        wrapper_enabled=True,
        field_wrapper_enabled=False,
    )
    .field(
        "submit",
        field_wrapper_class="offset-2",
        field_wrapper_enabled=True,
    )
).render(form)

And this is how it looks like

Form rendered in Bootstrap 5 favor

As you can see in the example, we use default_field method for overwriting the options of all fields by default. We also use field method for overwriting the options for a specific field. The field method takes multiple input name arguments, so that you can overwrite options for multiple fields at once like this

html = (context
    .field("email", "password", label_class="my-custom-class", ...)
)

Please notice that, the order of default_field and field method calls matter. When field is called, the current default field options will be used as the default values. So if you make the calls in order like this

html = (context
    .field("email", row_class="row")
    .default_field(label_class="my-custom-class")
)

The label_class for email field here will be form-label instead of my-custom-class since when it's called, the original default value was still form-label.

To customize the form element, you can use the form method like this

html = (context
    .form(
        method="POST",
        action="/sign-up",
        enctype="application/x-www-form-urlencoded",
        form_class="my-form",
        form_attrs=dict(custom="value")
    )
)

Field HTML structure

In general, the field HTML structure can be controlled by the option values and it looks like this

<!-- enabled by .row_enabled, default: true -->
<div class=".row_class" {.row_attrs}>
  <!-- enabled by .wrapper_enabled, default: false -->
  <div class=".wrapper_class" {.wrapper_attrs}>
    <!-- enabled by .label_enabled, default: true -->
    <label class=".label_class" for="email" {.label_attrs}>Email</label>
    <!-- enabled by .field_wrapper_enabled, default: false -->
    <div class=".field_wrapper" {.field_wrapper_attrs}>
      <input class=".field_class" id="email" name="email" type="email" value="" {.field_attrs}>
      <!-- enabled by .help_enabled, default: true -->
      <div class=".help_class" {.helper_attrs}>Your super secret password</div>
      <!-- enabled by .error_enabled, default: true -->
      <div class=".error_class" {.error_attrs}>Bad password</div>
    </div>
  </div>
</div>

Integrate with template engine

We want to make it as easy as possible to integrate with template engine such as Jinja. That's why we use chained method calls for customizing the form. You should be able to pass the form and RenderContext objects and write all your form customization from the template. This way, you don't get your view relative code pollute your controller code. For example, after passing form and render_context object, you can write this in Jinja:

<h1>New user</h1>

{{
    renderer_context
        .default_field(
            row_class="row mb-3",
            label_class="form-label col-2",
            field_wrapper_class="col-10",
            field_wrapper_enabled=True,
        )
        .field(
            "agree_terms",
            wrapper_class="offset-2",
            wrapper_enabled=True,
            field_wrapper_enabled=False,
        )
        .field(
            "submit",
            field_wrapper_class="offset-2",
            field_wrapper_enabled=True,
        )
    ).render(form)
}}

Feedbacks

Feedbacks, bugs reporting or feature requests are welcome 🙌, just please open an issue. No guarantee we have time to deal with them, but will see what we can do.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wtforms-bootstrap5-0.1.2.tar.gz (10.8 kB view details)

Uploaded Source

Built Distribution

wtforms_bootstrap5-0.1.2-py3-none-any.whl (9.2 kB view details)

Uploaded Python 3

File details

Details for the file wtforms-bootstrap5-0.1.2.tar.gz.

File metadata

  • Download URL: wtforms-bootstrap5-0.1.2.tar.gz
  • Upload date:
  • Size: 10.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.12 CPython/3.10.2 Linux/5.13.0-1023-aws

File hashes

Hashes for wtforms-bootstrap5-0.1.2.tar.gz
Algorithm Hash digest
SHA256 690fc4e347eb7d3aa4efeeba750762d4298b7210e791cc6db31007fa3b36d778
MD5 23cdb9d61ae33ecf9e0649e956951bc3
BLAKE2b-256 66ae82500b0a4f50fdfe1f0386a24c24cdcf8bfc399ded18b565aabf1fda7399

See more details on using hashes here.

File details

Details for the file wtforms_bootstrap5-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for wtforms_bootstrap5-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9b859ac4fded542c2dc84913cec51b8c5e742f310904174dcd8ea7954a48a493
MD5 3ee187a4823da4ea4cbe514c4006c4fd
BLAKE2b-256 95a5535d8e25651c2aff5434b4bb0f1ba39e7997f2101d2473e46faf1e33695b

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page