{"id":14065245,"url":"https://github.com/LaunchPlatform/wtforms-bootstrap5","last_synced_at":"2025-07-29T20:31:47.726Z","repository":{"id":40301525,"uuid":"504290731","full_name":"LaunchPlatform/wtforms-bootstrap5","owner":"LaunchPlatform","description":"Simple library for rendering WTForms in HTML as Bootstrap 5 form controls","archived":false,"fork":false,"pushed_at":"2023-09-15T00:52:07.000Z","size":126,"stargazers_count":25,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-16T10:11:54.061Z","etag":null,"topics":["forms","jinja2","python","template","wtforms"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LaunchPlatform.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-06-16T20:04:03.000Z","updated_at":"2025-03-29T01:26:33.000Z","dependencies_parsed_at":"2024-05-28T00:29:50.785Z","dependency_job_id":"04dd3ace-d4e1-45d0-8e2b-d45c5cbe39a3","html_url":"https://github.com/LaunchPlatform/wtforms-bootstrap5","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/LaunchPlatform/wtforms-bootstrap5","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fwtforms-bootstrap5","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fwtforms-bootstrap5/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fwtforms-bootstrap5/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fwtforms-bootstrap5/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LaunchPlatform","download_url":"https://codeload.github.com/LaunchPlatform/wtforms-bootstrap5/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LaunchPlatform%2Fwtforms-bootstrap5/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265574540,"owners_count":23790627,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["forms","jinja2","python","template","wtforms"],"created_at":"2024-08-13T07:04:23.238Z","updated_at":"2025-07-29T20:31:47.430Z","avatar_url":"https://github.com/LaunchPlatform.png","language":"Python","readme":"# WTForms-Bootstrap5\nSimple library for rendering WTForms in HTML as Bootstrap 5 form controls\n\n**Notice: this project is still in very early stage, the API may change a lots rapidly**\n\n## Features\n\n- **MIT licensed** - it doesn't infect your code\n- **Light weight** - not much code and little dependencies\n- **Latest Bootstrap 5** - generates forms in latest Bootstrap 5 style \n- **Highly customizable** - you can generate different kind of Bootstrap 5 form controls and layouts\n- **Template engine friendly** - chained method calls making it easy to integrate with template engine\n- **Covered with automatic tests** - yep, we have test cases\n\n## Why?\n\nEverytime I build a website with [WTForms](https://wtforms.readthedocs.io), I spend way too much time in writing HTML and [Jinja template](https://jinja.palletsprojects.com/) for rendering a form as [Bootstrap 5 form controls](https://getbootstrap.com/docs/5.2/forms/overview/).\nWork smart is an important value we have here at [Launch Platform](https://launchplatform.com), so I wonder why not make a library for making rendering Bootstrap 5 style WTForms controls easily?\nSo here you go, wtforms-bootstrap5 is created, open sourced under MIT license.\nIt's a simple Python library for rendering WTForms in Bootstrap 5 favor.\n\n## Install\n\nTo install the formatter, simply run\n\n```bash\npip install wtforms-bootstrap5\n```\n\n## Example\n\nFirst, you define your form as you would usually do with WTForms:\n\n```python\nfrom wtforms import Form\nfrom wtforms import EmailField\nfrom wtforms import PasswordField\nfrom wtforms import SelectField\nfrom wtforms import BooleanField\nfrom wtforms import SubmitField\n\n\nclass MyForm(Form):\n    email = EmailField(\"Email\", render_kw=dict(placeholder=\"Foobar\"))\n    password = PasswordField(\"Password\", description=\"Your super secret password\")\n    city = SelectField(\"City\", choices=[\"Los Angle\", \"San Francisco\", \"New York\"])\n    agree_terms = BooleanField(\"I agrees to terms and service\")\n    submit = SubmitField()\n\n```\n\nThen you can use `RenderContext` for rendering your form like this\n\n```python\nfrom wtforms_bootstrap5 import RendererContext\n\nform = MyForm()\ncontext = RendererContext()\nhtml = context.render(form)\n```\n\nThe form will be rendered as HTML like\n\n```html\n\u003cform method=\"POST\"\u003e\u003cdiv class=\"mb-3\"\u003e\u003clabel class=\"form-label\" for=\"email\"\u003eEmail\u003c/label\u003e\u003cinput class=\"form-control\" id=\"email\" name=\"email\" type=\"email\" value=\"\"\u003e\u003c/div\u003e\n\u003cdiv class=\"mb-3\"\u003e\u003clabel class=\"form-label\" for=\"password\"\u003ePassword\u003c/label\u003e\u003cinput class=\"form-control\" id=\"password\" name=\"password\" type=\"password\" value=\"\"\u003e\u003cdiv class=\"form-text\"\u003eYour super secret password\u003c/div\u003e\u003c/div\u003e\n\u003cdiv class=\"mb-3\"\u003e\u003clabel class=\"form-label\" for=\"city\"\u003eCity\u003c/label\u003e\u003cselect class=\"form-select\" id=\"city\" name=\"city\"\u003e\u003coption value=\"Los Angle\"\u003eLos Angle\u003c/option\u003e\u003coption value=\"San Francisco\"\u003eSan Francisco\u003c/option\u003e\u003coption value=\"New York\"\u003eNew York\u003c/option\u003e\u003c/select\u003e\u003c/div\u003e\n\u003cdiv class=\"mb-3\"\u003e\u003cdiv class=\"form-check\"\u003e\u003clabel class=\"form-check-label\" for=\"agree_terms\"\u003eI agrees to terms and service\u003c/label\u003e\u003cinput class=\"form-check-input\" id=\"agree_terms\" name=\"agree_terms\" type=\"checkbox\" value=\"y\"\u003e\u003c/div\u003e\u003c/div\u003e\n\u003cdiv class=\"mb-3\"\u003e\u003cinput class=\"btn btn-primary\" id=\"submit\" name=\"submit\" type=\"submit\" value=\"Submit\"\u003e\u003c/div\u003e\u003c/form\u003e\n```\n\nAnd it will look like this\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/default-style-example.png?raw=true\" alt=\"Form rendered in Bootstrap 5 favor\" /\u003e\n\u003c/p\u003e\n\nBy default, a sensible simple layout style will be used.\n\n## Customize the form\n\nThere are many similar open source libraries out there, but most of them are very hard to customize.\nOnce you adopt it, then you can only render your form in a specific style.\nAs a result, I found myself writing HTML manually without using the library to save time.\n\nTo avoid the same mistake, we want to make wtforms-bootstrap5 very easy to customize without compromising too much of its reusability.\nHere's an example how you can turn the example above into a column based form.\n\n```python\nhtml = (\n    renderer_context\n    .form(action=\"/sign-up\")\n    .default_field(\n        row_class=\"row mb-3\",\n        label_class=\"form-label col-2\",\n        field_wrapper_class=\"col-10\",\n        field_wrapper_enabled=True,\n    )\n    .field(\n        \"agree_terms\",\n        wrapper_class=\"offset-2\",\n        wrapper_enabled=True,\n        field_wrapper_enabled=False,\n    )\n    .field(\n        \"submit\",\n        field_wrapper_class=\"offset-2\",\n        field_wrapper_enabled=True,\n    )\n).render(form)\n```\n\nAnd this is how it looks like\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/column-style-example.png?raw=true\" alt=\"Form rendered in Bootstrap 5 favor\" /\u003e\n\u003c/p\u003e\n\nAs you can see in the example, we use `default_field` method for overwriting the options of all fields by default.\nWe also use `field` method for overwriting the options for a specific field.\nThe `field` method takes multiple input name arguments, so that you can overwrite options for multiple fields at once like this\n\n```python\nhtml = (context\n    .field(\"email\", \"password\", label_class=\"my-custom-class\", ...)\n)\n```\n\nPlease notice that, **the order of `default_field` and `field` method calls matter**.\nWhen `field` is called, the current default field options will be used as the default values.\nSo if you make the calls in order like this\n\n```python\nhtml = (context\n    .field(\"email\", row_class=\"row\")\n    .default_field(label_class=\"my-custom-class\")\n)\n```\n\nThe `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`.\n\nTo customize the form element, you can use the `form` method like this\n\n```python\nhtml = (context\n    .form(\n        method=\"POST\",\n        action=\"/sign-up\",\n        enctype=\"application/x-www-form-urlencoded\",\n        form_class=\"my-form\",\n        form_attrs=dict(custom=\"value\")\n    )\n)\n```\n\n### Add submit button or other fields\n\nSometimes, define a submit button for each form is not desirable.\nOr, the form could be automatically generated and doesn't come with a submit button.\nIn those cases, you can use `add_field` to add any extra fields into the end of the form.\nLike this:\n\n```python\nhtml = (\n    renderer_context\n    .add_field(\"submit\", SubmitField())\n    .field(\n        \"submit\",\n        field_wrapper_class=\"offset-2\",\n        field_wrapper_enabled=True,\n    )\n).render(form)\n```\n\nSince adding a submit button is very common, so you can also use `add_submit` instead if the field to add is a `SubmitField`.\nThe default submit field name is `submit`, so you don't need to provide it if you want to make it `submit`.\nArguments of `SubmitField` can be passed in, such as `label`.\n\n```python\nhtml = (\n    renderer_context\n    .add_submit(label=\"Update\")\n    .field(\n        \"submit\",\n        field_wrapper_class=\"offset-2\",\n        field_wrapper_enabled=True,\n    )\n).render(form)\n```\n\nAs you can see in the example, the decorate options also work for the newly added submit field.\nIf you want to change the default submit field class, you can pass in `submit_field_cls` argument when creating the context like this.\n\n```python\nhtml = (\n    RenderContext(submit_field_cls=SubmitButton)\n    .add_submit()\n).render(form)\n```\n\n### Field HTML structure\n\nIn general, the field HTML structure can be controlled by the option values and it looks like this\n\n```html\n\u003c!-- enabled by .row_enabled, default: true --\u003e\n\u003cdiv class=\".row_class\" {.row_attrs}\u003e\n  \u003c!-- enabled by .wrapper_enabled, default: false --\u003e\n  \u003cdiv class=\".wrapper_class\" {.wrapper_attrs}\u003e\n    \u003c!-- enabled by .label_enabled, default: true --\u003e\n    \u003clabel class=\".label_class\" for=\"email\" {.label_attrs}\u003eEmail\u003c/label\u003e\n    \u003c!-- enabled by .field_wrapper_enabled, default: false --\u003e\n    \u003cdiv class=\".field_wrapper\" {.field_wrapper_attrs}\u003e\n      \u003cinput class=\".field_class\" id=\"email\" name=\"email\" type=\"email\" value=\"\" {.field_attrs}\u003e\n      \u003c!-- enabled by .help_enabled, default: true --\u003e\n      \u003cdiv class=\".help_class\" {.helper_attrs}\u003eYour super secret password\u003c/div\u003e\n      \u003c!-- enabled by .error_enabled, default: true --\u003e\n      \u003cdiv class=\".error_class\" {.error_attrs}\u003eBad password\u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/div\u003e\n```\n\n## Integrate with template engine\n\nWe want to make it as easy as possible to integrate with template engine such as [Jinja](https://jinja.palletsprojects.com/).\nThat's why we use chained method calls for customizing the form.\nYou should be able to pass the `form` and `RenderContext` objects and write all your form customization from the template.\nThis way, you don't get your view relative code pollute your controller code.\nFor example, after passing `form` and `render_context` object, you can write this in Jinja:\n\n```html\n\u003ch1\u003eNew user\u003c/h1\u003e\n\n{{\n    renderer_context\n        .default_field(\n            row_class=\"row mb-3\",\n            label_class=\"form-label col-2\",\n            field_wrapper_class=\"col-10\",\n            field_wrapper_enabled=True,\n        )\n        .field(\n            \"agree_terms\",\n            wrapper_class=\"offset-2\",\n            wrapper_enabled=True,\n            field_wrapper_enabled=False,\n        )\n        .field(\n            \"submit\",\n            field_wrapper_class=\"offset-2\",\n            field_wrapper_enabled=True,\n        )\n    ).render(form)\n}}\n```\n\n## Feedbacks\n\nFeedbacks, bugs reporting or feature requests are welcome 🙌, just please open an issue.\nNo guarantee we have time to deal with them, but will see what we can do.\n","funding_links":[],"categories":["Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLaunchPlatform%2Fwtforms-bootstrap5","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLaunchPlatform%2Fwtforms-bootstrap5","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLaunchPlatform%2Fwtforms-bootstrap5/lists"}