DEV Community

Avash Karn
Avash Karn

Posted on

Build a basic flask feed like chat app to know how message application works

Build a simple beginner friendly chat app (one big group message board) with a feed format using Flask: Complete Beginner's Guide

Introduction

In this tutorial, we'll build a real-time messaging application using Flask. You'll learn how to create user authentication, send and receive messages. By the end, you'll have a working chat application that multiple users can access at the same time or simultaneously. This is a perfect project for beginners who want to understand how messaging platforms work behind the scenes.

Prerequisites

Before starting, make sure you have:

  • Python 3.8 or higher installed
  • Basic knowledge of Python
  • pip (Python package manager)
  • A text editor or IDE (VS Code recommended)
  • Familiarity with command line basics

Project Setup

Let's start by creating a folder for our project:

mkdir flask-messenger
cd flask-messenger
python -m venv venv
source venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Now install the required packages:

pip install flask flask-sqlalchemy werkzeug
Enter fullscreen mode Exit fullscreen mode

Create a file called app.py and we'll build our application here.

Database Models

First, we need to define how our data will be stored in the database, today we'll use sqlite3 using flask SQLalchemy. We'll create two tables: User (for storing user information) and Message (for storing messages) and foreign key to connect them.

from flask import Flask, render_template, request, session, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
from datetime import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///messenger.db'
app.config['SECRET_KEY'] = 'your-secret-key-here'
UPLOAD_FOLDER = 'static/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

os.makedirs(UPLOAD_FOLDER, exist_ok=True)
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    password = db.Column(db.String(255), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.utcnow)
    messages = db.relationship('Message', backref='author', lazy=True)

class Message(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    content = db.Column(db.String(500), nullable=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    timestamp = db.Column(db.DateTime, default=datetime.utcnow)
Enter fullscreen mode Exit fullscreen mode

The User model or table stores username and password. The Message model stores the message content, and links to the user who sent it.

User Authentication

Now let's create registration and login functionality (important for security and also provides convinience):

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

        if User.query.filter_by(username=username).first():
            return 'Username already exists'

        hashed_password = generate_password_hash(password)
        user = User(username=username, password=hashed_password)
        db.session.add(user)
        db.session.commit()
        return redirect(url_for('login'))

    return '''
    <form method="POST">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <button type="submit">Register</button>
    </form>
    '''

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

        if user and check_password_hash(user.password, password):
            session['user_id'] = user.id
            session['username'] = user.username
            return redirect(url_for('messenger'))

        return 'Invalid credentials'

    if session.get('user_id'):
        return redirect(url_for('messenger'))

    return '''
    <form method="POST">
        <input type="text" name="username" placeholder="Username" required>
        <input type="password" name="password" placeholder="Password" required>
        <button type="submit">Login</button>
    </form>
    <p>No account? <a href="/register">Register here</a></p>
    '''
Enter fullscreen mode Exit fullscreen mode

When a user registers, we hash their password using generate_password_hash for security. When they login, we compare the entered password with the hashed password using check_password_hash. If correct, we store their user_id in the session.

Messaging Feature

Now let's create the main messenger page where users can send and receive messages:

@app.route('/messenger', methods=['GET', 'POST'])
def messenger():
    if not session.get('user_id'):
        return redirect(url_for('login'))

    if request.method == 'POST':
        content = request.form.get('content')

        if content:
            message = Message(
                content=content,
                user_id=session['user_id']
            )
            db.session.add(message)
            db.session.commit()

        return redirect(url_for('messenger'))

    all_messages = Message.query.order_by(Message.timestamp.desc()).all()
    return render_template('messenger.html', messages=all_messages, current_user=session.get('username'))

@app.route('/logout')
def logout():
    session.clear()
    return redirect(url_for('login'))
Enter fullscreen mode Exit fullscreen mode

These route checks if the user is logged in. If they post a message, we save it to the database. Then we display all messages on the page

HTML Template

Create a file templates/messenger.html:

<!DOCTYPE html>
<html>
<head>
    <title>Flask Messenger</title>
    <style>
        body { font-family: Arial; margin: 20px; }
        .messages { border: 1px solid #ccc; padding: 10px; height: 400px; overflow-y: auto; margin-bottom: 20px; }
        .message { margin: 10px 0; padding: 10px; background: #f0f0f0; border-radius: 5px; }
        .username { font-weight: bold; }
        .timestamp { font-size: 0.8em; color: #666; }
        img { max-width: 200px; margin-top: 10px; }
    </style>
</head>
<body>
    <h1>Flask Messenger</h1>
    <p>Logged in as: <strong>{{ current_user }}</strong> | <a href="/logout">Logout</a></p>

    <div class="messages">
        {% for message in messages %}
        <div class="message">
            <div class="username">{{ message.author.username }}</div>
            <div class="timestamp">{{ message.timestamp.strftime('%Y-%m-%d %H:%M') }}</div>
            {% if message.content %}
                <p>{{ message.content }}</p>
            {% endif %}
        </div>
        {% endfor %}
    </div>

    <form method="POST" enctype="multipart/form-data">
        <textarea name="content" placeholder="Type a message..." rows="3"></textarea><br>

        <button type="submit">Send</button>
    </form>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Running the Application

Create the database, paste this code at the end of the app.py and run the app:

if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True, host='0.0.0.0', port=5000)
Enter fullscreen mode Exit fullscreen mode

Open your terminal and run:

python app.py
Enter fullscreen mode Exit fullscreen mode

Visit http://localhost:5000 in your browser. Register a new account, then login. You can now send messages!

Testing

To test the app:

  1. Register two different users
  2. Login as User 1, send a message
  3. Open a new browser window, login as User 2
  4. Both users should see messages from each other

Conclusion

Congratulations! You've built a functional messaging application. You learned how to create database models with SQLAlchemy, implement user authentication with password hashing, store and retrieve messages, and use Flask sessions for user management.
Thank you for reading till end

Top comments (0)