So i have a login form and signup form on a single html page. I have custom validators for signup form that are not working.
The routes.py looks like this
#app.route("/", methods=['GET', 'POST'])
def home():
login_form = LoginForm(request.form, prefix="login-form")
regis_form = RegistrationForm(request.form, prefix="register-form")
return render_template('home.html', login_form=login_form, regis_form=regis_form)
#app.route("/register", methods=['POST'])
def register():
regis_form = RegistrationForm(request.form, prefix='register-form')
if regis_form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(regis_form.password_regis.data).decode('utf-8')
user = User(username=regis_form.username_regis.data, email=regis_form.email_regis.data, password=hashed_password)
db.session.add(user)
db.session.commit()
flash('Your account has been created! You are now able to log in', 'success')
return redirect(url_for('home'))
return redirect(url_for('home'))
#app.route("/login", methods=['POST'])
def login():
login_form = LoginForm(request.form, prefix='login-form')
if login_form.validate_on_submit():
user = User.query.filter_by(email=login_form.email_login.data).first()
if user and bcrypt.check_password_hash(user.password, login_form.password_login.data):
login_user(user, remember=login_form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check email and password', 'danger')
return redirect(url_for('home'))
forms.py
class RegistrationForm(FlaskForm):
username_regis = StringField('Username',
validators=[DataRequired(), Length(min=5, max=20)])
email_regis = EmailField('Email',
validators=[DataRequired(), Email()])
password_regis = PasswordField('Password', validators=[DataRequired()])
submit_regis = SubmitField('Sign Up')
def validate_username_regis(self, username_regis):
user = User.query.filter_by(username=username_regis.data).first()
if user:
raise ValidationError('That username is taken. Please choose a different one.')
def validate_email_regis(self, email_regis):
user = User.query.filter_by(email=email_regis.data).first()
if user:
raise ValidationError('That email is taken. Please choose a different one.')
class LoginForm(FlaskForm):
email_login = EmailField('Email',
validators=[DataRequired(), Email()])
password_login = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit_login = SubmitField('Login')
home.html
<div>
<form method="POST" action="{{ url_for('login') }}">
{{ login_form.hidden_tag() }}
<fieldset class="form-group">
<div class="form-group">
{% if login_form.email_login.errors %}
{{ login_form.email_login(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in login_form.email_login.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ login_form.email_login(class="form-control mb-2", placeholder="Email") }}
{% endif %}
</div>
<div class="form-group">
{% if login_form.password_login.errors %}
{{ login_form.password_login(class="form-control is-invalid") }}
<div class="invalid-feedback">
{% for error in login_form.password_login.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ login_form.password_login(class="form-control mb-2", placeholder="Password") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ login_form.submit_login(class="btn btn-danger") }}
</div>
</form>
</div>
<div class="" id="regis">
<form method="POST" action="{{ url_for('register') }}">
{{ regis_form.hidden_tag() }}
<fieldset class="form-group">
<div class="form-group">
{% if regis_form.username_regis.errors %}
{{ regis_form.username_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.username_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.username_regis(class="form-control form-control-md mb-2", placeholder="Username") }}
{% endif %}
</div>
<div class="form-group">
{% if regis_form.email_regis.errors %}
{{ regis_form.email_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.email_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.email_regis(class="form-control form-control-md mb-2", placeholder="Email") }}
{% endif %}
</div>
<div class="form-group">
{% if regis_form.password_regis.errors %}
{{ regis_form.password_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.password_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.password_regis(class="form-control form-control-md mb-2", placeholder="Password") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ regis_form.submit_regis(class="btn btn-danger") }}
</div>
</form>
</div>
Previously I had both forms on the same home route, custom validators were working but if i submitted register form with errors purposefully, then the login form also shows error like input required. So to fix that I did this, but now signup form is not validating custom validators
After your data has failed validation, you execute return redirect(url_for('home')). That results into a GET on the home route. That populates a new instance of the form: regis_form = RegistrationForm(request.form, prefix="register-form"). Your error information will be lost, it is on a different instance.
To get the error information, your register() route will need to render the template using render_template('home.html', login_form=login_form, regis_form=regis_form), not do the redirect. Do not forget to create a new instance of LoginForm, otherwise your rendering will fail.
Related
The form does not show any errors when i try to submit it, it just reload the sign up page even though there are errors in my input, i used an if statement to see there are errors and the for loop to display each error but they do not seem to be working. what am i doing wrong and how can i solve it?
main.py
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from wtforms.fields import StringField, EmailField, PasswordField, SubmitField, TextAreaField, BooleanField
from wtforms.validators import Length, DataRequired, Email, EqualTo, Optional
class SignUp(FlaskForm):
username = StringField(label="username", validators=[Length(min=5, max=20), DataRequired(message="enter a name")])
first_name = StringField(label="first name", validators=[Length(min=5, max=20), DataRequired()])
last_name = StringField(label="last name", validators=[Length(min=5, max=20), DataRequired()])
email = EmailField(label="email", validators=[DataRequired(), Length(min=6)])
password = PasswordField(label="password", validators=[Length(min=8, max=40), DataRequired()])
confirm_password = PasswordField(label="confirm password", validators=[EqualTo(password), DataRequired()])
message = TextAreaField(label="message", validators=[Length(min=10, max=120), Optional()])
agree = BooleanField(label="I agree to the terms and conditions")
submit = SubmitField(label="Sign Up")
app = Flask(__name__)
app.config["SECRET_KEY"] = "uhr78hv98n4n8y7b6em98x8794c87x3m98xtmmsce9n8ce"
#app.route("/")
#app.route("/home")
def home():
return render_template("index.html")
#app.route("/signup", methods=["POST", "GET"])
#app.route("/register", methods=["POST", "GET"])
def sign_up():
form = SignUp()
if request.method == "POST":
if form.validate_on_submit():
pass
return render_template("signup.html", form=form)
if __name__ == "__main__":
app.run(debug=True)
signup.html
{% extends "base.html" %} {% block head %}
<title>Sign UP</title>
{% endblock head %} {% block body %}
<h1>Sign Up</h1>
<form method="POST" action="{{ url_for('sign_up') }}" novalidate>
{{ form.csrf_token }}
<div class="field">
{{ form.username.label }} {{ form.username }} {% if form.username.errors %}
{% for error in form.username.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.first_name.label }} {{ form.first_name }} {% if
form.first_name.errors %} {% for error in form.first_name.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.last_name.label }} {{ form.last_name }} {% if form.last_name.errors
%} {% for error in form.last_name.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.email.label }} {{ form.email }} {% if form.email.errors %} {% for
error in form.email.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.password.label }} {{ form.password }} {% if form.password.errors %}
{% for error in form.password.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.confirm_password.label }} {{ form.confirm_password }} {% if
form.confirm_password.errors %} {% for error in form.confirm_password.error
%}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
<div class="field">
{{ form.message.label }} {{ form.message }} {% if form.message.errors %} {%
for error in form.message.error %}
<p style="color: red">{{ error }}</p>
{% endfor %} {% endif %}
</div>
{{ form.agree }} <br />
{{ form.submit }}
</form>
{% endblock body %}
I have been working on a website for the past while using flask, python and bootstrap. I added footer to my website and I would like a "contact me" form in the footer. Below is my current code for creating a contact form and displaying this form.
class ContactForm(FlaskForm):
email = StringField("", validators=[DataRequired(), Email()])
content = TextAreaField("", validators=[DataRequired(), length(min=2, max=500)])
submit = SubmitField("Submit")
<form method="POST" action="">
<div class="form-group">
{{ form.email.label(class="form-control-label") }}
{% if form.email.errors %}
{{ form.email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.content.label(class="form-control-label") }}
{% if form.content.errors %}
{{ form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.submit(class="btn btn-outline-info") }}
</div>
</form>
I created this footer in my "layout.html" file which is the base file that all other html documents extend from so that all pages will have this same footer.
The issue is that then I need to create and instance of this form object on every page of my application and handle the validate_on_submit on every page. (Sample code below)
#app.route("/random_page", methods=["GET", "POST"])
def random_page():
form = ContactForm()
if form.validate_on_submit():
# code to send the email goes here
return render_template("random_page")
I am looking for an easier way to do this so that I don't need to repeat code on every page and so that It can be considerably simpler. I am not very experienced with flask and would highly appreciate the help.
Use the #app.context_processor decorator, documentation to inject an instance of your contact form into the template context for all templates. For example:
#app.context_processor
def inject():
return dict(
contact_form=ContactForm(),
)
Then re-write the form's HTML to use the contact_form template variable, also adding in an appropriate action route.
<form method="POST" action="{{url_for('contact')}}">
<div class="form-group">
{{ contact_form.email.label(class="form-control-label") }}
{% if contact_form.email.errors %}
{{ contact_form.email(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.email.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ contact_form.email(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ contact_form.content.label(class="form-control-label") }}
{% if contact_form.content.errors %}
{{ contact_form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in contact_form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ contact_form.content(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ contact_form.submit(class="btn btn-outline-info") }}
</div>
</form>
Then add a route to solely handle this form's postback:
#app.route("/contact", methods=["POST"])
def contact():
form = ContactForm()
if form.validate_on_submit():
# code to send the email goes here
# blah blah
So I have 2 forms, login form and registration form, on home.html, which show up as a modal when clicked on the login button, which looks like as follows:
home.html
<button type="button" class="btn btn-outline-danger" data-bs-toggle="modal" data-bs-target="#loginModal">
Login
</button>
<div class="modal fade" id="loginModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Sign In</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<button id="login" class="btn btn-login btn-md">Log In</button>
<button id="regis" class="btn btn-login btn-md">Register</button><hr style="margin-top: 0px;">
<div class="" id="login">
<form method="POST" action="">
{{ login_form.hidden_tag() }}
<fieldset class="form-group">
<div class="form-group">
{% if login_form.email_login.errors %}
{{ login_form.email_login(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in login_form.email_login.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ login_form.email_login(class="form-control form-control-md mb-2", placeholder="Email") }}
{% endif %}
</div>
<div class="form-group">
{% if login_form.password_login.errors %}
{{ login_form.password_login(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in login_form.password_login.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ login_form.password_login(class="form-control form-control-md mb-2", placeholder="Password") }}
{% endif %}
</div>
<div class="form-check">
{{ login_form.remember(class="form-check-input") }}
{{ login_form.remember.label(class="form-check-label") }}
</div>
</fieldset>
<div class="form-group">
{{ login_form.submit_login(class="btn btn-danger") }}
<small class="text-muted ml-2">
Forgot Password?
</small>
</div>
</form>
</div>
<div class="" id="regis">
<form method="POST" action="">
{{ regis_form.hidden_tag() }}
<fieldset class="form-group">
<div class="form-group">
{% if regis_form.username_regis.errors %}
{{ regis_form.username_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.username_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.username_regis(class="form-control form-control-md mb-2", placeholder="Username") }}
{% endif %}
</div>
<div class="form-group">
{% if regis_form.email_regis.errors %}
{{ regis_form.email_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.email_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.email_regis(class="form-control form-control-md mb-2", placeholder="Email") }}
{% endif %}
</div>
<div class="form-group">
{% if regis_form.password_regis.errors %}
{{ regis_form.password_regis(class="form-control form-control-md is-invalid") }}
<div class="invalid-feedback">
{% for error in regis_form.password_regis.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ regis_form.password_regis(class="form-control form-control-md mb-2", placeholder="Password") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ regis_form.submit_regis(class="btn btn-danger") }}
</div>
</form>
</div>
</div>
</div>
</div>
</div>
The two "Log In" and "Register" buttons are tabs i.e. by clicking on "Register" button you will see registration form and vice versa which is controlled by JavaScript.
My forms.py file looks like this:
forms.py
class RegistrationForm(FlaskForm):
username_regis = StringField('Username',
validators=[DataRequired(), Length(min=2, max=20)])
email_regis = StringField('Email',
validators=[DataRequired(), Email()])
password_regis = PasswordField('Password', validators=[DataRequired()])
submit_regis = SubmitField('Sign Up')
class LoginForm(FlaskForm):
email_login = StringField('Email',
validators=[DataRequired(), Email()])
password_login = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit_login = SubmitField('Login')
and below is the routes.py function:
routes.py
#app.route("/", methods=['GET', 'POST'])
def home():
login_form = LoginForm()
regis_form = RegistrationForm()
if request.method == 'POST':
if login_form.validate_on_submit() and login_form.submit_login.data:
user = User.query.filter_by(email=login_form.email_login.data).first()
if user and bcrypt.check_password_hash(user.password, login_form.password_login.data):
login_user(user, remember=login_form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Login Unsuccessful. Please check email and password', 'danger')
if regis_form.validate_on_submit() and regis_form.submit_regis.data:
hashed_password = bcrypt.generate_password_hash(regis_form.password_regis.data).decode('utf-8')
user = User(username=regis_form.username_regis.data, email=regis_form.email_regis.data, password=hashed_password)
db.session.add(user)
db.session.commit()
flash('Your account has been created! You are now able to log in', 'success')
return redirect(url_for('home'))
return render_template('home.html', login_form=login_form, regis_form=regis_form)
Now, The problem is that when I try to login using an email that is not registered it flashes me
'Login Unsuccessful. Please check email and password'
which is ok as it should do this. but when I open the login modal again and open the registration tab, the * username_regis password_regis and email_regis* fields are showing me 'The field is required' error.
It should not show me this error on registration form because I never submitted this form.
I want to get rid of these error messages. I will deeply appreciate any help.
The code you wrote is as follows:
if request.method == 'POST':
if login_form.validate_on_submit() and login_form.submit_login.data:
<SNIP>
if regis_form.validate_on_submit() and regis_form.submit_regis.data:
<SNIP>
That means that both forms are are validated, no matter what form you submit. So when you submit one form the other will always show errors. The preferred solution is to post to different routes. On your form the action parameter will need to be filled and you will need two functions, one for each route. You than will also get rid of asking if form data is available. It must be, because you are on that route.
I have designed a form to update a task. The form will get the details of the task into the update form and while submitting that form the form.validate_on_submit does not work and redirects again to the same form with the previous values. Here are my routes and template code. I have used {{ form.csrf_token }}. But similar logic works with the newTask route.
Update Route
#main.route('/update/<int:id>',methods=['POST','GET'])
#login_required
def update(id):
if form.validate_on_submit():
t.task_name = form.task_name.data
t.assignee = form.assignee.data
t.deal_size = form.deal_size.data
t.lead_status = form.lead_status.data
t.stage = form.stage.data
t.priority = form.priority.data
t.submission_date = form.date.data
db.session.add(t)
db.session.commit()
return redirect('/')
form = NewTaskForm()
t = Tasks.query.get_or_404(id)
return render_template("update.html",form = form , t = t)
update.html
<form method="POST" action="/update/{{ t.id }}">
{{ form.csrf_token }}
<div class="form-group">
{{ form.task_name.label }}{{ form.task_name(class='form-control',value = t.task_name ) }}
{% if form.task_name.errors %}
{% for error in form.task_name.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.assignee.label }}{{ form.assignee(class='form-control',value = t.assignee) }}
{% if form.assignee.errors %}
{% for error in form.assignee.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.deal_size.label }}{{ form.deal_size(class='form-control',value = t.deal_size) }}
{% if form.deal_size.errors %}
{% for error in form.deal_size.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.lead_status.label }}{{ form.lead_status(class='form-control',value = t.lead_status) }}
{% if form.lead_status.errors %}
{% for error in form.lead_status.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-check padding-none">
{{ form.stage.label(class='form-check-label') }}{{ form.stage(class='form-check-input customRadio',value = t.stage.data) }}
{% if form.stage.errors %}
{% for error in form.stage.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
<div class="form-group">
{{ form.date.label }}{{ form.date(class='form-control',value = t.submission_date.date()) }}
{% if form.date.errors %}
{% for error in form.date.errors %}
<div class="alert alert-danger" role="alert">
{{ error }}
</div>
{% endfor %}
{% endif %}
</div>
{{ form.submit(class="btn btn-outline-primary btn-block") }}
</form>
newTask route
#main.route('/new-task',methods=['POST','GET'])
#login_required
def newTask():
form = NewTaskForm()
if form.validate_on_submit():
t = Tasks()
t.task_name = form.task_name.data
t.assignee = form.assignee.data
t.deal_size = form.deal_size.data
t.lead_status = form.lead_status.data
t.stage = form.stage.data
t.priority = form.priority.data
t.submission_date = form.date.data
db.session.add(t)
db.session.commit()
return redirect('/')
return render_template("newtask.html",form = form)
If you want to redirect the user to the new form use:
#main.route('/update/<int:id>',methods=['POST','GET'])
#login_required
def update(id):
if form.validate_on_submit():
# do something and then redirect
return redirect(url_for('confirm'))
return render_template("update.html",form = form , t = t)
Probably, you need to create a new function for the 'confirmation site' if you haven't done already.
You can look up the flask documentation if you want to have a better understanding of
url_for :
It accepts the name of the function as its first argument and any number of keyword arguments, each corresponding to a variable part of the URL rule. Unknown variable parts are appended to the URL as query parameters.
Here you can find a good explanation as well:
create-dynamic-urls-in-flask
I'm writing a Flask application that works sort of like a blog. I generated the text boxes with wtforms, but whenever I click on the button to save the text, nothing happens. I get no errors.
I've tried adding print statements to my code, and everything is working fine except that Flask is not receiving the POST request. Clicking the button does absolutely nothing.
This is the code for the endpoint. I added a print() statement after if request.method but nothing printed out, so I'm assuming it's not receiving the POST request:
#app.route("/newtext", methods=["GET", "POST"])
#login_required
def newtext():
form = NewPost()
if request.method == "POST" and form.validate():
new_post = Texts(user_id=current_user.id, title=form.title.data, content=form.content.data)
db.session.add(new_post)
db.session.commit()
new_click = UserActions(user_id=current_user.id, action=4)
db.session.add(new_click)
db.session.commit()
last_text = db.session.query(Texts).order_by(Texts.id.desc()).first()
text_id = last_text.id
text_version = TextVersions(content=form.content.data, user_id=current_user.id, text_id=text_id)
db.session.add(text_version)
db.session.commit()
plaintext = BeautifulSoup(form.content.data)
text_summary = Grammar.summary(plaintext.get_text())
return render_template("summary.html", text_id=text_id, text_summary=text_summary)
else:
return render_template("basiceditor.html", form=form)
And this is the html code for the webpage. It renders okay (the GET method clearly works) but the button does nothing:
<div class="container mt-5">
<div class="content-section">
<form method="POST" action="/newtext">
{{ form.hidden_tag() }}
<fieldset class="form-group">
<legend class="border-bottom mb-4">{{ legend }}</legend>
<div class="form-group">
{{ form.title.label(class="form-control-label") }}
{% if form.title.errors %}
{{ form.title(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.title.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.title(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.content.label(class="form-control-label") }}
{% if form.content.errors %}
{{ form.content(class="form-control form-control-lg is-invalid") }}
<div class="invalid-feedback">
{% for error in form.content.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.content(class="form-control form-control-lg", id="controleditor") }}
{% endif %}
</div>
</fieldset>
<div class="form-group">
{{ form.submit(class="btn btn-success") }}
</div>
</form>
</div>
</div>
The app reports no errors. It should save the text to the database and send the person to the summary.html page, but clicking on the button does nothing. I am completely stumped.