Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialErik Malmberg
1,465 PointsValidation form not working
I'm trying to use validation forms on my login for the flask "Build a Social Network" course, but the validation is not working - even if I leave the form blank and hit "submit", I get no error back.
Here's the code:
from flask import Flask, g, render_template, flash, redirect, url_for
from flask_login import LoginManager
import forms
import models
app = Flask(__name__)
app.secret_key = "76^Xdadsadsadasdsa_^"
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
@login_manager.user_loader
def load_user(userid):
try:
return models.User.get(models.User.id == userid)
except models.DoesNotExist:
return None
@app.before_request
def before_request():
"""Connect to database before each request"""
g.db = models.DATABASE
g.db.connect()
@app.after_request
def after_request(response):
"""Close the database connection after each request"""
g.db.close()
return response
@app.route("/register",methods=["GET","POST"])
def register():
form = forms.RegisterForm()
if form.validate_on_submit():
flash("Successful registration", "success")
models.User.create_user(
username=form.username.data,
email=form.email.data,
password=form.password.data
)
return redirect(url_for("index"))
return render_template("register.html",form=form)
@app.route("/")
def index():
return "Hi"
if __name__ == "__main__":
models.initialize()
try:
models.User.create_user(
username="usernamehere",
email="email@email.com",
password="password",
admin=True)
except ValueError:
pass
app.run(debug=True,port=5500)
forms.py:
from flask_wtf import Form
from wtforms import StringField, PasswordField
from wtforms.validators import DataRequired, Regexp, ValidationError, Email, Length, EqualTo
from models import User
def name_exists(form, field):
if User.select().where(User.username == field.data).exists():
raise ValidationError("User with that name already exists")
def email_exists(form, field):
if User.select().where(User.email == field.data).exists():
raise ValidationError("User with that email already exists")
class RegisterForm(Form):
username = StringField(
"Username",
validators=[
DataRequired(),
Regexp(
r'^[a-zA-Z0-9_]+$', message=("Username should be one word, letters, "
"numbers and underscores only")
),
name_exists
])
email = StringField(
"Email",
validators=[DataRequired(),
Email(),
email_exists
])
password = PasswordField(
"Password",
validators=[DataRequired(),
Length(min=2),
EqualTo("password2",message="Passwords must match")
])
password2 = PasswordField(
"Confirm Password",
validators=[DataRequired()]
)
macros.html:
{% macro render_field(field) %}
<div class="field">
{% if field.errors %}
{% for errors in field.errors %}
<div class="notification error">{{ error }}</div>
{% endfor %}
{% endif %}
{{ field(placeholder=field.label.text) }}
</div>
{% endmacro %}
register.html:
{% from "macros.html" import render_field %}
<form method="POST" action="" class="form">
{{ form.hidden_tag() }}
{% for field in form %}
{{ render_field(field) }}
{% endfor %}
<button type="submit" id="submit">Register</button>
</form>
models.py:
import datetime
from flask_login import UserMixin
from flask_bcrypt import generate_password_hash
from peewee import *
DATABASE = SqliteDatabase("social.db")
class User(UserMixin, Model):
username = CharField(unique=True)
email = CharField(unique=True)
password = CharField(max_length=100)
joined_at = DateTimeField(default=datetime.datetime.now) #datetime.datetime.now() will set time to WHEN script is run, don't use paranthesis
is_admin = BooleanField(default=False)
class Meta:
database = DATABASE
order_by = ("-joined_at",)
@classmethod
def create_user(cls, username, email, password, admin=False):
try:
cls.create(
username=username,
email=email,
password=generate_password_hash(password),
is_admin=admin)
except IntegrityError:
raise ValueError("User already exists")
def initialize():
DATABASE.connect()
DATABASE.create_tables([User], safe=True)
DATABASE.close()
2 Answers
Erik Malmberg
1,465 PointsLol, found the error.
{% if field.errors %}
{% for errors in field.errors %}
<div class="notification error">{{ error }}</div>
Was the culprit. Used error variable for "errors"
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsSo without seeing your forms.py and your template that serves up the page within your app. It is hard to say, but my safe assumption would be that the template that displays the form that you redirect back to when a form is invalid. Is either not pulling the errors out of the form or if you are using Flash messages to display a generic error for Form. Your register method looks like it has a Flash message for a valid form but not an invalid one.
Let me know if this helps you find the problem. And if you are running this inside Workspaces, if you Share the Workspace and provide the share link I can have a look. Otherwise if you cannot seem to find the answer, you will need to provide forms.py and the template file too so I dont have to make assumptions on what is there! :-)
Erik Malmberg
1,465 PointsHey Chris, sorry - didn't add them, added them now though. Can't find any typos or errors - maybe it has to do something with flask wtf forms being updated?
"FlaskWTFDeprecationWarning: "flask_wtf.Form" has been renamed to "FlaskForm" and will be removed in 1.0."
Chris Howell
Python Web Development Techdegree Graduate 49,702 PointsChris Howell
Python Web Development Techdegree Graduate 49,702 PointsAhh nice! Glad you found it! :)