D73 #100DaysOfCode

D73 #100DaysOfCode. Today I implemented a user registraion page and enforced users to login to access the site.

Read Time3 Minutes, 22 Seconds

Day 73! Today I learned how to implement a user login page.

Yesterday I made a database and made some test users that could log in to the site, but now I needed to implement a registration page to make it easier for users.

So I started by addressing my User class and more specifically the password variable, at the moment the password is stored in plain text and if data breaches and general IT experience has taught me anything it’s “Don’t do that”.

There is a module I can load in that allows me to hash strings and then check that hash against the password.

from werkzeug.security import generate_password_hash, check_password_hash

So this is what my User class now looks like.

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    posts = db.relationship('Post', backref='author', lazy='dynamic')

    def set_password(self, password):
        self.password_hash = generate_password_hash(password)

    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

    def __repr__(self):
        return '<User {}>'.format(self.username)

After addressing the password issue I can now start creating my login page. There is a module we can import that can handle this.

pip install flask-login

I’m just going to quickly explain the rest of the steps if you are keen to see in detail how this was implemented check out the guide here.

I created a login HTML page and also added a route for the Register page.

{% extends "base.html" %}

{% block content %}
    <h1>Register</h1>
    <form action="" method="post">
        {{ form.hidden_tag() }}
        <p>
            {{ form.username.label }}<br>
            {{ form.username(size=32) }}<br>
            {% for error in form.username.errors %}
            <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>
            {{ form.email.label }}<br>
            {{ form.email(size=64) }}<br>
            {% for error in form.email.errors %}
            <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>
            {{ form.password.label }}<br>
            {{ form.password(size=32) }}<br>
            {% for error in form.password.errors %}
            <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>
            {{ form.password2.label }}<br>
            {{ form.password2(size=32) }}<br>
            {% for error in form.password2.errors %}
            <span style="color: red;">[{{ error }}]</span>
            {% endfor %}
        </p>
        <p>{{ form.submit() }}</p>
    </form>
{% endblock %}
@app.route('/register', methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('index'))
    form = RegistrationForm()
    if form.validate_on_submit():
        user = User(username=form.username.data, email=form.email.data)
        user.set_password(form.password.data)
        db.session.add(user)
        db.session.commit()
        flash('Congratulations, you are now a registered user!')
        return redirect(url_for('login'))
    return render_template('register.html', title='Register', form=form)

Also, I created a form to handle the data for the page.

class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    password2 = PasswordField(
        'Repeat Password', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Register')

    def validate_username(self, username):
        user = User.query.filter_by(username=username.data).first()
        if user is not None:
            raise ValidationError('Please use a different username.')

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user is not None:
            raise ValidationError('Please use a different email address.')

It seems pretty complicated at a high level, but it’s really not that hard to understand and coming from me, that’s saying something.

The cool thing about having this login and register page is that you can specify what pages require a login, so say if you had an admin page you could have a login restriction on that page. It’s so easy to implement, you just page the following code under your route.

@login_required

So now comes the demo of it all in action.

0 0
Happy
Happy
0 %
Sad
Sad
0 %
Excited
Excited
0 %
Sleppy
Sleppy
0 %
Angry
Angry
0 %
Surprise
Surprise
0 %

Leave a Reply

Your email address will not be published. Required fields are marked *

Close