If you want to use the built-in support:
from wtforms.ext.sqlalchemy.orm
import model_form
UserForm = model_form(User, _exclude = ['_pw_hash'])
If you want to use the separate WTForms-Alchemy package:
from wtforms_alchemy
import ModelForm
class UserForm(ModelForm):
class Meta:
model = User
exclude = ['_pw_hash']
Handle user input in your Flask app by creating forms with the Flask-WTForm library. Enforce field validation and create a frontend experience for users.,Our form is going to need input fields, as well as a way of validating the content of those fields once submitted. We can import field types directly from the WTForms package, and validators from the wtforms.validators package:,Flask-WTF comes packaged with WTForms as a dependency: the two libraries are intended to be used together, as opposed to one obfuscating the other. The core of Flask-WTF is a class called FlaskForm, which we extend with the form classes we define ourselves. This is mostly for convenience, as creating classes which extend FlaskForm inherently gives us some out-of-the-box logic related to validation, etc.:,Jinja templates will render the actual HTML forms that users will see. As we'll soon discover, Flask makes bridging the gap between Python models and HTML forms easy.
$ pip3 install flask flask - wtf
/flask-wtforms-tutorial├── / flask_wtforms_tutorial│├── / static│├── / templates│├── __init__.py│├── forms.py│└── routes.py├── config.py└── wsgi.py
""
"Form object declaration."
""
from flask_wtf
import FlaskForm
...
""
"Form object declaration."
""
from flask_wtf
import FlaskForm
from wtforms
import StringField, TextField, SubmitField
from wtforms.validators
import DataRequired, Length
...
""
"Form object declaration."
""
from flask_wtf
import FlaskForm
from wtforms
import StringField, TextField, SubmitField
from wtforms.validators
import DataRequired, Length
class ContactForm(FlaskForm):
""
"Contact form."
""
name = StringField(
'Name',
[DataRequired()]
)
email = StringField(
'Email',
[
Email(message = ('Not a valid email address.')),
DataRequired()
]
)
body = TextField(
'Message',
[
DataRequired(),
Length(min = 4,
message = ('Your message is too short.'))
]
)
recaptcha = RecaptchaField()
submit = SubmitField('Submit')
field = FieldType(
'LABEL',
validators = [ExampleValidator(message = "ERROR MESSAGE")],
)
Published: Wed 2020-02-26
When you start using the script, you should provide your own SECRET_KEY.
$ pwgen - s 30 1 QFLl4I17MpsBebNB18nrKPP6aVnf7M
#!/usr/bin/python3 "RSVP autoform" # Copyright 2020 Tero Karvinen http: //TeroKarvinen.com from flask import Flask, render_template, flash, redirect from flask_sqlalchemy import SQLAlchemy from wtforms.ext.sqlalchemy.orm import model_form from flask_wtf import FlaskForm import wtforms app = Flask(__name__) db = SQLAlchemy(app) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///autoformed.db" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["SECRET_KEY"] = "dUCF)mtd9MAoZ?;R|8*iB^.+TCV//0" class Reply(db.Model): id = db.Column(db.Integer, primary_key = True) coming = db.Column(db.Boolean, nullable = False) email = db.Column(db.String, nullable = False) name = db.Column(db.String, nullable = False) field_args = { "email": { "validators": [wtforms.validators.Email()] } } ReplyForm = model_form(model = Reply, base_class = FlaskForm, db_session = db.session, field_args = field_args) @app.before_first_request def beforeFirstRequest(): db.create_all() @app.route("/", methods = ["GET", "POST"]) def index(): form = ReplyForm() if form.validate_on_submit(): reply = Reply() form.populate_obj(reply) db.session.add(reply) db.session.commit() flash("Your reply has been added. Welcome!") return redirect("/") replies = db.session.query(Reply) return render_template("replies.html", form = form, replies = replies) def main(): app.run(debug = True) if __name__ == "__main__": main()
<!doctype html>
<html lang=en>
<head>
<title>Joining an Event Example</title>
<meta charset="utf-8">
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}
<h1>Hello Tero</h1>
{% endblock %}
<p>Learn Flask automatic forms at <a href="TeroKarvinen.com">TeroKarvinen.com</a>
</body>
</html>
#!/usr/bin/python3 "RSVP autoform" # Copyright 2020 Tero Karvinen http: //TeroKarvinen.com from flask import Flask, render_template, flash, redirect from flask_sqlalchemy import SQLAlchemy from wtforms.ext.sqlalchemy.orm import model_form from flask_wtf import FlaskForm import wtforms app = Flask(__name__) db = SQLAlchemy(app) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///autoformed.db" app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False app.config["SECRET_KEY"] = "dUCF)mtd9MAoZ?;R|8*iB^.+TCV//0" class Reply(db.Model): id = db.Column(db.Integer, primary_key = True) coming = db.Column(db.Boolean, nullable = False) email = db.Column(db.String, nullable = False) name = db.Column(db.String, nullable = False) field_args = { "email": { "validators": [wtforms.validators.Email()] } } ReplyForm = model_form(model = Reply, base_class = FlaskForm, db_session = db.session, field_args = field_args) @app.before_first_request def beforeFirstRequest(): db.create_all() @app.route("/", methods = ["GET", "POST"]) def index(): form = ReplyForm() if form.validate_on_submit(): reply = Reply() form.populate_obj(reply) db.session.add(reply) db.session.commit() flash("Your reply has been added. Welcome!") return redirect("/") replies = db.session.query(Reply) return render_template("replies.html", form = form, replies = replies) def main(): app.run(debug = True) if __name__ == "__main__": main()
<!doctype html>
<html lang=en>
<head>
<title>Joining an Event Example</title>
<meta charset="utf-8">
</head>
<body>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}
<h1>Hello Tero</h1>
{% endblock %}
<p>Learn Flask automatic forms at <a href="TeroKarvinen.com">TeroKarvinen.com</a>
</body>
</html>
{% extends "base.html" %}
{% block body %}
<h1>Replies</h1>
<form method=post action="/">
{{ form.csrf_token }}
{% for field in form if not field.name in ["csrf_token"] %}
<p>{{ field.label }}: {{ field }} <b>{{ " ".join(field.errors) }}</b></p>
{% endfor %}
<input type="submit">
</form>
<h2>Replies</h2>
{% for reply in replies %}
<p>{{ reply.name }}</p>
{% endfor %}
{% endblock %}
create the form from the request form value if the data is submitted via the HTTP POST method and args if the data is submitted as GET.,When you are working with WTForms you have to define your forms as classes first. I recommend breaking up the application into multiple modules (Large Applications as Packages) for that and adding a separate module for the forms.,When you have to work with form data submitted by a browser view, code quickly becomes very hard to read. There are libraries out there designed to make this process easier to manage. One of them is WTForms which we will handle here. If you find yourself in the situation of having many forms, you might want to give it a try.,Now to the template side. When you pass the form to the templates, you can easily render them there. Look at the following example template to see how easy this is. WTForms does half the form generation for us already. To make it even nicer, we can write a macro that renders a field with label and a list of errors if there are any.
from wtforms
import Form, BooleanField, StringField, PasswordField, validators
class RegistrationForm(Form):
username = StringField('Username', [validators.Length(min = 4, max = 25)])
email = StringField('Email Address', [validators.Length(min = 6, max = 35)])
password = PasswordField('New Password', [
validators.DataRequired(),
validators.EqualTo('confirm', message = 'Passwords must match')
])
confirm = PasswordField('Repeat Password')
accept_tos = BooleanField('I accept the TOS', [validators.DataRequired()])
@app.route('/register', methods = ['GET', 'POST'])
def register():
form = RegistrationForm(request.form)
if request.method == 'POST'
and form.validate():
user = User(form.username.data, form.email.data,
form.password.data)
db_session.add(user)
flash('Thanks for registering')
return redirect(url_for('login'))
return render_template('register.html', form = form)
{% 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 %}
{% from "_formhelpers.html" import render_field %}
<form method=post>
<dl>
{{ render_field(form.username) }}
{{ render_field(form.email) }}
{{ render_field(form.password) }}
{{ render_field(form.confirm) }}
{{ render_field(form.accept_tos) }}
</dl>
<p><input type=submit value=Register>
</form>