Below is the registration form python file: I'm following a tutorial by Corey Shafer: https://www.youtube.com/watch?v=803Ei2Sq-Zs&t=269s , and I basically followed every step so far, except for the bootstrap. How can I return "username already taken" when I try to sign up with the same username?
I'm not exactly sure what to do, looked up a bunch of answers but haven't really found anything.
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flask_pract.models import User
class Reg_Form(FlaskForm):
username = StringField('Username', validators=[DataRequired(),Length(min=5,max=20)])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Sign Up')
def validate_username(self, username):
user = User.query.filter_by(username = username.data).first()
if user:
raise ValidationError('That username is taken. Please choose a different one.')
def validate_email(self, email):
user = User.query.filter_by(username = email.data).first()
if user:
raise ValidationError('That email is taken. Please choose a different one.')
class Login_Form(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit = SubmitField('Login')
class UpdateAccountForm(FlaskForm):
username = StringField('Username', validators=[DataRequired(),Length(min=5,max=20)])
email = StringField('Email', validators=[DataRequired(), Email()])
submit = SubmitField('Sign Up')
Then routes python file here:
from flask import render_template, url_for, flash, redirect, request
from flask_pract import app, bcrypt, db
from flask_pract.reg_forms import Reg_Form, Login_Form
from flask_pract.models import User,Post
from flask_login import login_user, current_user, logout_user, login_required
@app.route("/")
def home():
return render_template('home.html')
@app.route("/about")
def about():
return render_template('about.html',title="About")
@app.route("/register", methods=['GET','POST'])
def register():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = Reg_Form()
if form.validate_on_submit():
hashed_pw = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username = form.username.data, email=form.email.data, password = hashed_pw)
db.session.add(user)
db.session.commit()
flash('Your account has been successfully created! You are now able to log in.')
return redirect(url_for('login'))
return render_template('register.html',title="Register", form = form)
@app.route("/login", methods=['GET','POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = Login_Form()
if form.validate_on_submit():
user = User.query.filter_by(email = form.email.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user,remember=form.remember.data)
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('account'))
else:
flash(f'Login unsuccessful. Please check your email and password')
return render_template('login.html',title="Login", form = form)
@app.route("/logout")
def logout():
logout_user()
return redirect(url_for('home'))
@app.route("/account")
@login_required
def account():
image_file = url_for('static', filename='profile_pics/' + current_user.image_file)
return render_template('account.html', title ='Account',image_file=image_file )
Registration html:
{% extends "layout.html" %}
{% block content %}
<h1>It's the register page</h1>
<form method="POST" action="">
{{ form.hidden_tag() }}
{{form.username.label }}
{{form.username}}
{{form.email.label}}
{{form.email }}
{{form.password.label}}
{{form.password }}
{{form.confirm_password.label}}
{{form.confirm_password}}
{{form.submit}}
{% for field, errors in form.errors.items() %}
<small class="form-text text-muted ">
{{field}}
{{ ', '.join(errors) }}
</small>
{% endfor %}
</form>
<h1><a href="{{ url_for('login') }}">Already have an account?</a></h1>
{% endblock content %}
And models:
from datetime import datetime
from flask_pract import db, login_manager
from flask_login import UserMixin
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id=db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(20), unique = True, nullable = False)
email = db.Column(db.String(120), unique = True, nullable = False)
image_file = db.Column(db.String(20), nullable = False, default='default.jpg')
password = db.Column(db.String(60), nullable = False)
posts = db.relationship('Post',backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}','{self.email}','{self.image_file}')"
class Post(db.Model):
id = db.Column(db.Integer, primary_key = True)
title = db.Column(db.String(100), nullable = False)
date_posted = db.Column(db.DateTime, nullable = False, default = datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable = False)
def __repr__(self):
return f"Post('{self.title}','{self.date_posted}')"
Add the following line in the register route after the
if form.validate_on_submit():statement:Then remove the validations from the form file.