article

Tuesday, February 18, 2020

Login Register Sytem with Python Flask and Mysql


Login Register Sytem with Python Flask and Mysql

A complete login and registration system with Python Flask and MySQL

Table account

CREATE TABLE `accounts` (
  `id` int(11) NOT NULL,
  `fullname` varchar(200) NOT NULL,
  `username` varchar(50) NOT NULL,
  `password` varchar(255) NOT NULL,
  `email` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
#app.py
from flask import Flask, request, session, redirect, url_for, render_template
from flaskext.mysql import MySQL
import pymysql 
import re 

app = Flask(__name__)

# Change this to your secret key (can be anything, it's for extra protection)
app.secret_key = 'cairocoders-ednalan'

mysql = MySQL()
  
# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = ''
app.config['MYSQL_DATABASE_DB'] = 'testingdb'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)

# http://localhost:5000/pythonlogin/ - this will be the login page
@app.route('/pythonlogin/', methods=['GET', 'POST'])
def login():
 # connect
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
 
    # Output message if something goes wrong...
    msg = ''
    # Check if "username" and "password" POST requests exist (user submitted form)
    if request.method == 'POST' and 'username' in request.form and 'password' in request.form:
        # Create variables for easy access
        username = request.form['username']
        password = request.form['password']
        # Check if account exists using MySQL
        cursor.execute('SELECT * FROM accounts WHERE username = %s AND password = %s', (username, password))
        # Fetch one record and return result
        account = cursor.fetchone()
  
    # If account exists in accounts table in out database
        if account:
            # Create session data, we can access this data in other routes
            session['loggedin'] = True
            session['id'] = account['id']
            session['username'] = account['username']
            # Redirect to home page
            #return 'Logged in successfully!'
            return redirect(url_for('home'))
        else:
            # Account doesnt exist or username/password incorrect
            msg = 'Incorrect username/password!'
   
    return render_template('index.html', msg=msg)

# http://localhost:5000/register - this will be the registration page
@app.route('/register', methods=['GET', 'POST'])
def register():
 # connect
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
 
    # 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
        fullname = request.form['fullname']
        username = request.form['username']
        password = request.form['password']
        email = request.form['email']
  
  #Check if account exists using MySQL
        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.execute('INSERT INTO accounts VALUES (NULL, %s, %s, %s, %s)', (fullname, username, password, email)) 
            conn.commit()
  
            msg = 'You have successfully registered!'
    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)
 
# http://localhost:5000/home - this will be the home page, only accessible for loggedin users
@app.route('/')
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'))
 
# http://localhost:5000/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'))

# http://localhost:5000/profile - this will be the profile page, only accessible for loggedin users
@app.route('/profile')
def profile(): 
 # Check if account exists using MySQL
    conn = mysql.connect()
    cursor = conn.cursor(pymysql.cursors.DictCursor)
 
    # 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.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'))
 
 
 
if __name__ == '__main__':
    app.run(debug=True)
//index.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Login</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
 </head>
 <body style="background-color:#ccc;">
  <div class="login-box" >
  <div class="login-header">Login</div>
  <div class="login-body">
   <p>Please enter your username and password</p>
   <form class="form-group" action="{{ url_for('login') }}" method="post">
    <label>Username</label>
    <input type="text" class="form-control" name="username" placeholder="Username" id="username" required>
    <label>Password</label>
    <input type="password" class="form-control" name="password" placeholder="Password" id="password" required>
    <input type="checkbox" value="checked"><b>Remember</b>
    <input type="submit" value="Login" class="form-control btn btn-success " name="">
   </form>
   <div id="msg">{{ msg }}</div>
   <p>No account <a href="{{ url_for('register') }}">Register</a></p>
  </div>
 </div>
 </body>
</html>
//home.html
{% extends 'layout.html' %}

{% block title %}Home{% endblock %}

{% block content %}
<h1 class="h2">Dashboard</h1>
<p>Welcome back, {{ username }}!</p>
{% endblock %}
//layout.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>{% block title %}{% endblock %}</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
 <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
 </head>
 <body class="loggedin">
 <nav class="site-header sticky-top py-1">
      <div class="container d-flex flex-column flex-md-row justify-content-between">
        <a class="py-2" href="#">
          <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="d-block mx-auto"><circle cx="12" cy="12" r="10"></circle><line x1="14.31" y1="8" x2="20.05" y2="17.94"></line><line x1="9.69" y1="8" x2="21.17" y2="8"></line><line x1="7.38" y1="12" x2="13.12" y2="2.06"></line><line x1="9.69" y1="16" x2="3.95" y2="6.06"></line><line x1="14.31" y1="16" x2="2.83" y2="16"></line><line x1="16.62" y1="12" x2="10.88" y2="21.94"></line></svg>
        </a>
  <a class="py-2 d-none d-md-inline-block" href="{{ url_for('home') }}"><i class="fas fa-home"></i> Home</a>
  <a class="py-2 d-none d-md-inline-block" href="{{ url_for('profile') }}"><i class="fas fa-user-circle"></i> Profile</a>
  <a class="py-2 d-none d-md-inline-block" href="{{ url_for('logout') }}"><i class="fas fa-sign-out-alt"></i> Logout</a>
   </div>
    </nav>
 
 <div class="container-fluid">
      <div class="row">
        <nav class="col-md-2 d-none d-md-block bg-light sidebar">
          <div class="sidebar-sticky">
            <ul class="nav flex-column">
              <li class="nav-item">
                <a class="nav-link active" href="#">
                  <i class="fas fa-home"></i>
                  Dashboard <span class="sr-only">(current)</span>
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <i class="fas fa-shopping-cart"></i>
                  Orders
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
    <i class="fas fa-shopping-cart"></i>
                  Products
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <i class="fas fa-users"></i>
                  Customers
                </a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">
                  <i class="fas fa-download"></i>
                  Reports
                </a>
              </li>
            </ul>
   </div>
        </nav>

        <main role="main" class="col-md-9 ml-sm-auto col-lg-10 pt-3 px-4">
          <div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
            <div class="col-12">
   {% block content %}{% endblock %}
   </div>
          </div>
   </main>
   
      </div>
    </div>
 
 </body>
</html>
//profile.html
{% extends 'layout.html' %}

{% block title %}Profile{% endblock %}

{% block content %}
<h1>Profile Page</h1>
<div>
    <p>Your account details are below:</p>
    <table>
        <tr>
            <td>Name:</td>
            <td>{{ account['fullname'] }}</td>
        </tr>
  <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 %}
//register.html
<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>Register</title>
  <link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
  <link rel="stylesheet" href="../static/css/style.css">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.1/css/all.css">
  <!-- Google Fonts -->
  <link href='https://fonts.googleapis.com/css?family=Passion+One' rel='stylesheet' type='text/css'>
  <link href='https://fonts.googleapis.com/css?family=Oxygen' rel='stylesheet' type='text/css'>
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
 </head>
 <body style="background-color:#ccc;">
 <div class="container">
   <div class="row main">
    <div class="main-login main-center">
    <h5>Register New user or login existing account</h5>
     <form action="{{ url_for('register') }}" method="post" autocomplete="off"> 
      <div class="form-group">
       <label for="name" class="cols-sm-2 control-label">Your Name</label>
       <div class="cols-sm-10">
        <div class="input-group">
         <span class="input-group-addon"><i class="fa fa-user fa" aria-hidden="true"></i></span>
         <input type="text" class="form-control" name="fullname" id="fullname"  placeholder="Enter your Name"/>
        </div>
       </div>
      </div>
      <div class="form-group">
       <label for="email" class="cols-sm-2 control-label">Your Email</label>
       <div class="cols-sm-10">
        <div class="input-group">
         <span class="input-group-addon"><i class="fa fa-envelope fa" aria-hidden="true"></i></span>
         <input type="text" class="form-control" name="email" id="email"  placeholder="Enter your Email"/>
        </div>
       </div>
      </div>

      <div class="form-group">
       <label for="username" class="cols-sm-2 control-label">Username</label>
       <div class="cols-sm-10">
        <div class="input-group">
         <span class="input-group-addon"><i class="fa fa-users fa" aria-hidden="true"></i></span>
         <input type="text" class="form-control" name="username" id="username" placeholder="Enter your Username" required>
        </div>
       </div>
      </div>

      <div class="form-group">
       <label for="password" class="cols-sm-2 control-label">Password</label>
       <div class="cols-sm-10">
        <div class="input-group">
         <span class="input-group-addon"><i class="fa fa-lock fa-lg" aria-hidden="true"></i></span>
         <input type="password" class="form-control" name="password" placeholder="Password" id="password" required  placeholder="Enter your Password"/>
        </div>
       </div>
      </div>

      <div class="form-group ">
       <div id="msg">{{ msg }}</div>
       <input type="submit" value="Register" class="form-control btn btn-primary " name="">
       <p style="padding:5px;">
       <a href="{{ url_for('login') }}" class="btn btn-dark ">Login</a></p>
      
      </div>
      
     </form>
    </div>
   </div>
  </div>
 <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>  
 </body>
</html>
//style.css
body {
   background-color: #435165;
   margin: 0;
}

.login-box
  {
   height: 50%;
   width: 30%;
   border: 1px solid grey;
   margin-left: 35%;
   margin-top: 10%;
   position: relative;
        box-shadow: 21px 12px 24px 10px rgba(0, 0, 0, .5);
        background: #dadada;
  }
  .login-header
  {
   text-align: center;
   font-family: "vardhana",cursive;
   font-size: 35px;
   background: linear-gradient(to bottom, #00bfff 0%, #0000ff 100%);
   color:#fff;
   position: relative;
        box-shadow: 1px 3px 14px  rgba(0, 0, 0, .5);
  }
  .login-body
  {
   padding: 20px;
   line-height: 2;
  }
.msg {
 color: #721c24;
    background-color: #f8d7da;
    border-color: #f5c6cb;
 padding: .75rem 1.25rem;
    margin-bottom: 1rem;
    border: 1px solid transparent;
    border-radius: .25rem;
}  
.main{
  margin-top:50px;
}

h1.title { 
 font-size: 50px;
 font-family: 'Passion One', cursive; 
 font-weight: 400; 
}

hr{
 width: 10%;
 color: #fff;
}

.form-group{
 margin-bottom: 15px;
}

label{
 margin-bottom: 15px;
}

input,
input::-webkit-input-placeholder {
    font-size: 11px;
    padding-top: 3px;
}

.main-login{
  background-color: #fff;
    /* shadows and rounded borders */
    -moz-border-radius: 2px;
    -webkit-border-radius: 2px;
    border-radius: 2px;
    -moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    -webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
    box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);

}
.form-control {
    height: auto!important;
padding: 8px 12px !important;
}
.input-group {
    -webkit-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    -moz-box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
    box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.21)!important;
}
.main-center{
  margin-top: 30px;
  margin: 0 auto;
  max-width: 400px;
    padding: 10px 40px;
 background:#009edf;
     color: #FFF;
    text-shadow: none;
 -webkit-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
-moz-box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.31);

}
span.input-group-addon i {
    color: #fff;
    font-size: 17px;padding:10px;
}

.login-button{
 margin-top: 5px;
}

.login-register{
 font-size: 11px;
 text-align: center;
}

.site-header {
    background-color: rgba(0, 0, 0, .85);
    -webkit-backdrop-filter: saturate(180%) blur(20px);
    backdrop-filter: saturate(180%) blur(20px);
}
.site-header a { 
 color:#fff;
}

Related Post