DEV Community

Cover image for Building Your First Flask App: A Beginner's Guide
FredAbod
FredAbod

Posted on

Building Your First Flask App: A Beginner's Guide

Building Your First Flask App: A Beginner's Guide

Flask is a lightweight and powerful web framework for Python. In this guide, we’ll walk you through building your first Flask app, complete with user authentication (signup and login). By the end, you’ll have a fully functional app running on your local machine.

Let's Code


Prerequisites

Before we start, make sure you have the following:

  • Python installed (version 3.7 or higher)
  • Basic knowledge of Python
  • A code editor (e.g., VS Code)
  • MySQL installed locally or access to a MySQL database
  • A willingness to learn (and maybe some coffee ☕)

Step 1: Setting Up Your Environment

  1. Install Flask: lask is a tool that helps us build websites using Python. To install it, open your terminal and run:
   pip install flask flask-mysqldb werkzeug
Enter fullscreen mode Exit fullscreen mode
  1. Create Your Project Directory: Think of this as creating a folder where all your files will live. Run:
   mkdir myfirstFlaskApp
   cd myfirstFlaskApp
Enter fullscreen mode Exit fullscreen mode
  1. Set Up Your Database: Create a MySQL database named myDB and a table named user:
   CREATE DATABASE myDB;
   USE myDB;
   CREATE TABLE user (
       id INT AUTO_INCREMENT PRIMARY KEY,
       username VARCHAR(100) UNIQUE,
       password VARCHAR(255)
   );
Enter fullscreen mode Exit fullscreen mode

Step 2: Writing the Flask App

Create a file named app.py and add the following code:

from flask import Flask, render_template, request, flash, redirect, url_for, session
from flask_mysqldb import MySQL
from werkzeug.security import generate_password_hash, check_password_hash

app = Flask(__name__)

# MySQL Config
app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'your_mysql_password'
app.config['MYSQL_DB'] = 'myDB'
mysql = MySQL(app)

app.secret_key = 'your_secret_key'

@app.route('/')
def home():
    return render_template('index.html')

@app.route('/signup', methods=['GET', 'POST'])
def signup():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        hashed_password = generate_password_hash(password)

        try:
            cur = mysql.connection.cursor()
            cur.execute("INSERT INTO user (username, password) VALUES (%s, %s)", (username, hashed_password))
            mysql.connection.commit()
            cur.close()
            flash('Registration successful!', 'success')
            return redirect(url_for('login'))
        except:
            flash('Registration failed! Username might already exist.', 'error')
    return render_template('signup.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        cur = mysql.connection.cursor()
        cur.execute("SELECT * FROM user WHERE username = %s", [username])
        user = cur.fetchone()
        cur.close()

        if user and check_password_hash(user[2], password):
            session['username'] = username
            flash('Welcome back, {}!'.format(username), 'success')
            return redirect(url_for('home'))
        else:
            flash('Invalid username or password', 'danger')
    return render_template('login.html')

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

Step 3: Creating the HTML Templates

  1. Homepage (templates/index.html):
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Home Page</title>
       <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
   </head>
   <body>
       <div class="container mt-5">
           {% with messages = get_flashed_messages(with_categories=true) %}
               {% if messages %}
                   {% for category, message in messages %}
                       <div class="alert alert-{{ category }}">{{ message }}</div>
                   {% endfor %}
               {% endif %}
           {% endwith %}
           <div class="text-center">
               <h1>Welcome to My Flask App</h1>
               <p>This is the homepage.</p>
               <div class="btn-group">
                   <a href="/signup" class="btn btn-primary">Signup</a>
                   <a href="/login" class="btn btn-success">Login</a>
               </div>
           </div>
       </div>
   </body>
   </html>
Enter fullscreen mode Exit fullscreen mode
  1. Signup Page (templates/signup.html):
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Signup</title>
       <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
   </head>
   <body>
       <div class="container mt-5">
           {% with messages = get_flashed_messages() %}
               {% if messages %}
                   {% for message in messages %}
                       <div class="alert alert-info">{{ message }}</div>
                   {% endfor %}
               {% endif %}
           {% endwith %}
           <h2>Signup</h2>
           <form method="POST">
               <div class="form-group">
                   <label for="username">Username</label>
                   <input type="text" class="form-control" id="username" name="username" required>
               </div>
               <div class="form-group">
                   <label for="password">Password</label>
                   <input type="password" class="form-control" id="password" name="password" required>
               </div>
               <button type="submit" class="btn btn-primary">Register</button>
           </form>
       </div>
   </body>
   </html>
Enter fullscreen mode Exit fullscreen mode
  1. Login Page (templates/login.html):
   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <meta name="viewport" content="width=device-width, initial-scale=1.0">
       <title>Login</title>
       <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
   </head>
   <body>
       <div class="container mt-5">
           {% with messages = get_flashed_messages() %}
               {% if messages %}
                   {% for message in messages %}
                       <div class="alert alert-info">{{ message }}</div>
                   {% endfor %}
               {% endif %}
           {% endwith %}
           <h2>Login</h2>
           <form method="POST">
               <div class="form-group">
                   <label for="username">Username</label>
                   <input type="text" class="form-control" id="username" name="username" required>
               </div>
               <div class="form-group">
                   <label for="password">Password</label>
                   <input type="password" class="form-control" id="password" name="password" required>
               </div>
               <button type="submit" class="btn btn-primary">Login</button>
           </form>
       </div>
   </body>
   </html>
Enter fullscreen mode Exit fullscreen mode

Step 4: Running Your App

  1. Open your terminal and navigate to the project directory:
   cd myfirstFlaskApp
Enter fullscreen mode Exit fullscreen mode
  1. Run the app:
   python app.py
Enter fullscreen mode Exit fullscreen mode
  1. Open your browser and go to http://127.0.0.1:5000.

Code Explanation

from flask import Flask, render_template, request, flash, redirect, url_for, session
Enter fullscreen mode Exit fullscreen mode
  • Flask: This is the main tool we use to create the app.
  • render_template: Helps us show HTML pages to the user.
  • request: Lets us get data (like username and password) from forms.
  • flash: Displays messages like "Signup successful!" or "Login failed."
  • redirect and url_for: Help us move the user to another page.
  • session: Stores information about the user (like if they’re logged in).
from flask_mysqldb import MySQL
from werkzeug.security import generate_password_hash, check_password_hash
Enter fullscreen mode Exit fullscreen mode
  • MySQL: Connects our app to the database.
  • generate_password_hash: Turns passwords into a secret code (hash) for security.
  • check_password_hash: Checks if a password matches its secret code.

Setting Up the App

app = Flask(__name__)
Enter fullscreen mode Exit fullscreen mode

This creates the Flask app.

app.config['MYSQL_HOST'] = 'localhost'
app.config['MYSQL_USER'] = 'root'
app.config['MYSQL_PASSWORD'] = 'your_mysql_password'
app.config['MYSQL_DB'] = 'myDB'
mysql = MySQL(app)
Enter fullscreen mode Exit fullscreen mode

Here, we tell Flask how to connect to the database:

  • MYSQL_HOST: The address of the database (usually localhost for local machines).
  • MYSQL_USER and MYSQL_PASSWORD: The username and password for the database.
  • MYSQL_DB: The name of the database (myDB).
app.secret_key = 'your_secret_key'
Enter fullscreen mode Exit fullscreen mode

This is a secret key that Flask uses to keep things secure (like flash messages and sessions).


Homepage Route

@app.route('/')
def home():
    return render_template('index.html')
Enter fullscreen mode Exit fullscreen mode
  • @app.route('/'): This tells Flask to show the homepage when someone visits /.
  • render_template('index.html'): Displays the index.html file.

Signup Route

@app.route('/signup', methods=['GET', 'POST'])
def signup():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        hashed_password = generate_password_hash(password)
Enter fullscreen mode Exit fullscreen mode
  • methods=['GET', 'POST']: Allows the page to handle form submissions.
  • request.form['username']: Gets the username from the form.
  • generate_password_hash(password): Turns the password into a secret code.
        try:
            cur = mysql.connection.cursor()
            cur.execute("INSERT INTO user (username, password) VALUES (%s, %s)", (username, hashed_password))
            mysql.connection.commit()
            cur.close()
            flash('Registration successful!', 'success')
            return redirect(url_for('login'))
        except:
            flash('Registration failed! Username might already exist.', 'error')
Enter fullscreen mode Exit fullscreen mode
  • cur.execute: Adds the username and hashed password to the database.
  • flash: Shows a success or error message.
  • redirect(url_for('login')): Sends the user to the login page.

Login Route

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
Enter fullscreen mode Exit fullscreen mode
  • request.form['username'] and request.form['password']: Get the username and password from the form.
        cur = mysql.connection.cursor()
        cur.execute("SELECT * FROM user WHERE username = %s", [username])
        user = cur.fetchone()
        cur.close()
Enter fullscreen mode Exit fullscreen mode
  • cur.execute: Searches the database for the username.
  • cur.fetchone(): Gets the user’s data (if it exists).
        if user and check_password_hash(user[2], password):
            session['username'] = username
            flash('Welcome back, {}!'.format(username), 'success')
            return redirect(url_for('home'))
        else:
            flash('Invalid username or password', 'danger')
Enter fullscreen mode Exit fullscreen mode
  • check_password_hash(user[2], password): Checks if the password matches the secret code.
  • session['username']: Stores the username in the session (to remember the user).
  • flash: Shows a success or error message.

Running the App

if __name__ == '__main__':
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

This starts the app. The debug=True makes it easier to find errors.


Conclusion

Congratulations! 🎉 You’ve built your first Flask app with user authentication. This app can serve as a foundation for more advanced projects. Keep experimenting and happy coding!
Don't Forget To Drop A Like❤️

Happy Coding

Top comments (0)