简体   繁体   中英

rendering forms with flask + wtform

code in question:

from flask import Blueprint, render_template, abort
from flask.ext.wtf import Form
import os
from jinja2 import TemplateNotFound
from models import Member
from wtforms.ext.sqlalchemy.orm import model_form
@simple_page.route('/register')
def register():
    form = model_form(Member, Form)
    return render_template('register.html', form=form, name="bad")


class Member(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50), nullable=False)
    email = db.Column(db.String(50), nullable=False, unique=True)

and in my view:

        <p class="txt11 colorb">
        {{ form.name }}
        </p>

this outputs <UnboundField(TextField, (), {u'default': None, u'filters': [], u'validators': [<wtforms.validators.Required object at 0x7f62f59b5590>, <wtforms.validators.Length object at 0x7f62f59b55d0>]})> , not an actual field. how do i get an actual form/field with the wtform?

You're passing a form class not a form instance to the template. The model_form method generates a new class dynamically, which can be re-used, extended, and otherwise used like any other form subclass. It's also quite un-necessary to generate this form class on every run of your view, so you can move this call outside of your view.

You passing an uninstantiated class is also why you get strange behavior relating to UnboundField (which is how WTForms handles declarative field instantiation)

The fix is simple:

MemberForm = model_form(Member, base_class=Form)

@simple_page.route('/register')
def register():
    form = MemberForm(name=u'bad')
    return render_template('register.html', form=form)

You need to do a bit more work:

{{ form.name.label }} : {{ form.name()|safe }}

Or, you can use this handy snippet :

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

Of course, adjust the HTML rendered. Save that file somewhere in your templates directory and then in your main template. Here its formhelpers.html :

{% from "formhelpers.html" import render_field %}
<form method=post action="/register">
  <dl>
    {{ render_field(form.name) }}
    {{ render_field(form.email) }}
  </dl>
  <p><input type=submit value=Register>
</form>

I know this is pretty old, but I had the same problem and I want to share my solution for futures needs.

I also got the html rendered by "UnboundField". After fighting with the code I found out i'm using:

from wtforms import Form

And it's looks good, but when using Flask I had to do this:

from flask.ext.wtf import Form

Fixed my problem. Hope it's helped

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM