Search code examples
formsflaskjinja2wtforms

Flask-WT Form: How to pass additional parameters for form


In a jinja template I want to have a class for the form:

{% macro build_form(form) %}
<form class="{{ form.form_class  }}" role="form" method="post" action="" class="text-start">
  {{ form.hidden_tag() }}
  {% for field in form if field.widget.input_type != 'hidden' %}
  <div class="{{ field.render_kw.container2_class  }}">
    <div class="{{ field.render_kw.container1_class  }}">
      <label class="form-label"> {{ field.label }}</label>
      {{ field}}
    </div>
...

I want to pass it as a parameter of the form, something like

    user_form = UserForm(obj=user, form_class="row")

However, it's not recognized in the template. How and where can I send such parameters.


Solution

  • Easiest would be to create a custom form where you can pass the class name as a string keyword kwargs and then use this form as the base class for all your forms that need to support said class string. For example:

    class CustomForm(Form):
    
        def __init__(self, formdata=None, obj=None, prefix="", data=None, meta=None, **kwargs):
            self.form_class = kwargs.pop('form_class', None)
            super(CustomForm, self).__init__(formdata, obj, prefix, data, meta, **kwargs)
    

    Example in use:

    from flask import Flask, render_template_string
    from wtforms import Form, StringField
    
    app = Flask(__name__)
    
    
    class CustomForm(Form):
    
        def __init__(self, formdata=None, obj=None, prefix="", data=None, meta=None, **kwargs):
            self.form_class = kwargs.pop('form_class', None)
            super(CustomForm, self).__init__(formdata, obj, prefix, data, meta, **kwargs)
    
    
    class TestForm(CustomForm):
        first_name = StringField()
    
    
    html_template = '''
        <form class="{{ form.form_class }}" role="form" method="post" action="">
            {{ form.first_name }}
        </form>
    '''
    
    
    @app.route('/')
    def custom_form():
        _form = TestForm(form_class='form-class')
        return render_template_string(html_template, form=_form)
    
    
    if __name__ == '__main__':
        app.run()