Preparation
Create database, table and columns the data. Visit this link:
https://remotemysql.com/databases.php?action=new
Open phpmyadmin (click here), then login. Choose sql. Copy and paste the following script:
CREATE DATABASE IF NOT EXISTS `YOUR_DATABASE` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `YOUR_DATABASE`;
CREATE TABLE IF NOT EXISTS `accounts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `accounts` (`id`, `username`, `password`, `email`) VALUES (1, 'test', 'test', 'test@test.com');
There are 3 files important:
main.py
templates (folder). This is for html files only
static (folder). This is for CSS, JS and assets documentation
You can add the css file in the static folder by uploading this file (click here)
In main.py, please kindly copy and paste this:
Install this pip in the shell:
pip install mysql-connector
Now, You go to templates folder. Add file index.html. Copy and paste here:
Add login route as the main
Add route logout
#this will be the logout page
@app.route('/logout')
def logout():
# Remove session data, this will log the user out
session.pop('loggedin', None)
session.pop('id', None)
session.pop('username', None)
# Redirect to login page
return redirect(url_for('login'))
Add file register.html file in the templates folder
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Register</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
</head>
<body>
<div class="register">
<h1>Register</h1>
<div class="links">
<a href="{{ url_for('login') }}">Login</a>
<a href="{{ url_for('register') }}" class="active">Register</a>
</div>
<form action="{{ url_for('register') }}" method="post" autocomplete="off">
<label for="username">
<i class="fas fa-user"></i>
</label>
<input type="text" name="username" placeholder="Username" id="username" required>
<label for="password">
<i class="fas fa-lock"></i>
</label>
<input type="password" name="password" placeholder="Password" id="password" required>
<label for="email">
<i class="fas fa-envelope"></i>
</label>
<input type="email" name="email" placeholder="Email" id="email" required>
<div class="msg">{{ msg }}</div>
<input type="submit" value="Register">
</form>
</div>
</body>
</html>
Add route in main.py, the name is route('/register'):
# This will be the registration page, we need to use both GET and POST requests
@app.route('/register', methods=['GET', 'POST'])
def register():
# Output message if something goes wrong...
msg = ''
# Check if "username", "password" and "email" POST requests exist (user submitted form)
if request.method == 'POST' and 'username' in request.form and 'password' in request.form and 'email' in request.form:
# Create variables for easy access
username = request.form['username']
password = request.form['password']
email = request.form['email']
elif request.method == 'POST':
# Form is empty... (no POST data)
msg = 'Please fill out the form!'
# Show registration form with message (if any)
return render_template('register.html', msg=msg)
After: email = request.form['email']
Add:
# Check if account exists using MySQL
# cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cursor.execute('SELECT * FROM accounts WHERE username = %s', (username,))
account = cursor.fetchone()
# If account exists show error and validation checks
if account:
msg = 'Account already exists!'
elif not re.match(r'[^@]+@[^@]+\.[^@]+', email):
msg = 'Invalid email address!'
elif not re.match(r'[A-Za-z0-9]+', username):
msg = 'Username must contain only characters and numbers!'
elif not username or not password or not email:
msg = 'Please fill out the form!'
else:
# Account doesnt exists and the form data is valid, now insert new account into accounts table
cursor = db.cursor()
cursor.execute('INSERT INTO accounts VALUES (NULL, %s, %s, %s)', (username, password, email,))
# mysql.connection.commit()
msg = 'You have successfully registered!'
Now we can go back to our index.html file and change this line:
<a href="#">Register</a>
To:
<a href="{{ url_for('register') }}">Register</a>
Find the following code in the login route function:
return 'Logged in successfully!'
Replace with:
return redirect(url_for('home'))
In the main.py create the @app.route('/home'):
# this will be the home page, only accessible for loggedin users
@app.route('/home')
def home():
# Check if user is loggedin
if 'loggedin' in session:
# User is loggedin show them the home page
return render_template('home.html', username=session['username'])
# User is not loggedin redirect to login page
return redirect(url_for('login'))
In the templates folder, create the home.html:
{% extends 'layout.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h2>Home Page</h2>
<p>Welcome back, {{ username }}!</p>
{% endblock %}
We need create layout.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
</head>
<body class="loggedin">
<nav class="navtop">
<div>
<h1>Website Title</h1>
<a href="{{ url_for('home') }}"><i class="fas fa-home"></i>Home</a>
<a href="{{ url_for('profile') }}"><i class="fas fa-user-circle"></i>Profile</a>
<a href="{{ url_for('logout') }}"><i class="fas fa-sign-out-alt"></i>Logout</a>
</div>
</nav>
<div class="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
Add the profile route:
# this will be the profile page, only accessible for loggedin users
@app.route('/profile')
def profile():
# Check if user is loggedin
if 'loggedin' in session:
# We need all the account info for the user so we can display it on the profile page
# cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
cursor = db.cursor()
cursor.execute('SELECT * FROM accounts WHERE id = %s', (session['id'],))
account = cursor.fetchone()
# Show the profile page with account info
return render_template('profile.html', account=account)
# User is not loggedin redirect to login page
return redirect(url_for('login'))
Add profile.html:
{% extends 'layout.html' %}
{% block title %}Profile{% endblock %}
{% block content %}
<h2>Profile Page</h2>
<div>
<p>Your account details are below:</p>
<table>
<tr>
<td>Username:</td>
<td>{{ account['username'] }}</td>
</tr>
<tr>
<td>Password:</td>
<td>{{ account['password'] }}</td>
</tr>
<tr>
<td>Email:</td>
<td>{{ account['email'] }}</td>
</tr>
</table>
</div>
{% endblock %}