How to auto-generate full HTML from a WTForms form
Asked Answered
M

2

8

I'm trying to create a simple WTForms-based admin interface for an SQLAlchemy app, using Jinja2 templates.

I've read the docs of WTForms-Alchemy and I understand that it can auto-generate a form from my model just via a few lines of code, like:

class UserForm(ModelForm):
    class Meta:
        model = User

My problem is that even though I have this form auto-generated, I found no resource anywhere about how can I make it into a functional HTML page. There are a few snippets about rendering errors for fields, as well as some SO answers mentioning macros for rendering whole fields, but I found absolutely no resource about how to generate a full, functional form automatically.

// I understand that this is something what Flask-Admin might do already, I'm not using Flask so this is not a possibility unfortunately.

Mariannemariano answered 1/12, 2015 at 3:10 Comment(0)
L
10

WTForms leaves it up to you to figure out how to you want to render out your form after you pass it into your template. The simplest way to render a form would be to just iterate through your form and render the fields. When a field (or its label) is called, it emits HTML.

<form action="/some_url" method="POST">
   {% for field in form %}
       {{ field.label() }}
       {{ field() }}
   {% endfor %}

   <button type="submit" />
</form>

The macros provided here provide an automated way to generate HTML surrounding these fields.

Lur answered 29/12, 2015 at 23:37 Comment(2)
Nice, though it is printing out the CSRF Token label as well. {% if field.type != 'CSRFTokenField' %}...{% endif %} working so far.Arcadian
The link is outdated.Gnostic
H
0

You can use wtf.quick_form like this, in which case you'll have a totally generic form template. Mark up your db.Model members with info{} properties to set field display names etc

<form method="post" action="/{{route}}">
  <fieldset>
    {{ wtf.quick_form(form, button_map={'submit':'success'}) }}
    <input class="btn btn-success" type="submit" value="Submit" />  
    <button type="button" class="btn"><a href="/">Cancel</a></button>
  </fieldset>
</form>

Your form definition:

class MyobjectForm(BaseModelForm):
    class Meta:
        model = Myobject

Then your route handler looks like this:

@app.route('/myobject', methods=('GET', 'POST'))
def myobject_route():
    obj = Myobject()
    form = MyobjectForm(obj = obj)
    if form.validate_on_submit():
        form.populate_obj(obj)
        db.session.add(obj)
        db.session.commit()
        return redirect(url_for('index'))
    return render_template('form.j2', form=form, title='My Object', route='myobject')
Heaps answered 4/7, 2018 at 7:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.