I’m currently working on a 100 days of code project however I’m stuck. I’m unable to render the "Success.html" and "Denied.html" templates in my login route code. I’m including the python and html portions of the code. Any insight is appreciated. I think the problem is inside the login route code however I’ve hit a wall and don’t know what to try at the moment.
import email_validator
from flask import Flask, render_template, request
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms.validators import Email, Length, DataRequired, ValidationError
from wtforms import StringField, PasswordField, SubmitField
from email_validator import validate_email
# create a flask instance
app = Flask(__name__)
# CSRF protection
app.secret_key = "123456"
#disabling CSRF Protection
# app.config['WTF_CSRF_ENABLED'] = False
# create a form class
class LoginForm(FlaskForm):
def validate_email(self, field):
# Custom email validation using email_validator
try:
validate_email(field.data)
except Exception as e:
raise ValidationError(str(e))
email = StringField(label="Email", validators=[DataRequired(), Email()], render_kw={"size": 30})
password = PasswordField(label="Password", validators=[DataRequired(), Length(min=8)], render_kw={"size": 30})
submit = SubmitField(label="Log In")
# create a route decorator
@app.route('/', methods=["GET", "POST"])
def login():
form = LoginForm()
form.validate_on_submit()
print(request.method)
print(form.email.data)
print(form.password.data)
return render_template('login.html', form=form)
@app.route('/login', methods=["GET", "POST"])
def login_info():
form = LoginForm()
if form.validate_on_submit():
if form.email.data == "[email protected]" and form.password.data == "12345678":
print(request.method)
print(type(form.email.data))
print(type(form.password.data))
return render_template('success.html')
else:
return render_template('denied.html')
else:
return render_template('login.html', form=form)
if __name__ == "__main__":
app.run(debug=True)
The HTML code for the login page is this
<!DOCTYPE HTML>
<html>
<head>
<title>Login</title>
</head>
<body>
<div class="container">
<h1>Login Page</h1>
<form method="post" action="{{ url_for('login')}}" novalidate>
{{form.csrf_token}}
<p>
{{form.email.label}} <br> {{form.email}}
{% for err in form.email.errors %}
<span style="color:red">{{ err }}</span>
{% endfor %}
</p>
<p>
{{form.password.label}} <br> {{form.password}}
{% for err in form.password.errors %}
<span style="color:red">{{ err }}</span>
{% endfor %}
</p>
{{form.submit}}
</form>
</div>
</body>
</html>
2
Answers
You’re submitting your form to the wrong endpoint. The form’s
action
attribute referenceslogin
, notlogin_info
.Typically you’ll want the
GET
to the login view to just provide the form (login.html
) and thePOST
to processes the submitted login details and then redirect the user where you want them to go (or just showsuccess.html
in your case).You’ve somewhat complicated things by having 2 views that both take
GET
andPOST
but thelogin_info
one isn’t referenced anywhere in yourlogin.html
so it’s never actually used. Thelogin
view calls.validate_on_submit()
but then always just returns thelogin.html
and that’s why you don’t ever seesuccess.html
.