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
Now install the required packages:
pip install flask flask-sqlalchemy werkzeug
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)
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>
'''
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'))
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>
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)
Open your terminal and run:
python app.py
Visit http://localhost:5000 in your browser. Register a new account, then login. You can now send messages!
Testing
To test the app:
- Register two different users
- Login as User 1, send a message
- Open a new browser window, login as User 2
- 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)