Flask Projects With Source Code

Event Management System Project In Flask


Creating an advanced-level Event Management System using Flask and Bootstrap 5 involves designing a robust database structure, implementing Flask routes, and creating dynamic web pages. Below is a detailed implementation:

1. Database Structure

The database will include tables for users, events, attendees, event categories, and event organizers. We'll use SQLAlchemy for ORM.

Database Models


from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(100), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(200), nullable=False)
    role = db.Column(db.String(50), nullable=False)  # Admin, Organizer, Attendee
    events_organized = db.relationship('Event', backref='organizer', lazy=True)
    attendances = db.relationship('Attendance', backref='attendee', lazy=True)
class EventCategory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    events = db.relationship('Event', backref='category', lazy=True)
class Event(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(200), nullable=False)
    description = db.Column(db.Text, nullable=False)
    date = db.Column(db.DateTime, nullable=False)
    location = db.Column(db.String(200), nullable=False)
    capacity = db.Column(db.Integer, nullable=False)
    organizer_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    category_id = db.Column(db.Integer, db.ForeignKey('event_category.id'), nullable=False)
    attendees = db.relationship('Attendance', backref='event', lazy=True)
class Attendance(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
    registration_date = db.Column(db.DateTime, default=datetime.utcnow)

Flask Application Structure

Here’s the directory structure for the project:


advanced_event_management/
│
├── app/
│   ├── __init__.py                # Initialize the Flask app and database
│   ├── models.py                  # Database models (User , Event, Attendance, EventCategory)
│   ├── routes.py                  # Application routes and views
│   ├── forms.py                   # Forms for user registration, login, event posting, and applications
│   ├── static/                     # Static files (CSS, JS, images)
│   │   ├── css/
│   │   │   └── styles.css         # Custom CSS styles
│   │   └── js/
│   │       └── scripts.js         # Custom JavaScript files
│   └── templates/                 # HTML templates
│       ├── base.html              # Base layout for templates
│       ├── index.html             # Home page
│       ├── login.html             # Login page
│       ├── register.html          # Registration page
│       ├── dashboard.html          # User dashboard
│       ├── post_event.html        # Event posting page
│       ├── event_detail.html       # Event details page
│       └── my_events.html          # User's events page
│
├── migrations/                     # Database migration files (if using Flask-Migrate)
│
├── config.py                       # Configuration settings for the app
│
├── requirements.txt                # Python package dependencies
│
└── run.py                          # Entry point to run the application

2. Flask Application Setup

Install required packages:


pip install flask flask-sqlalchemy flask-wtf flask-login flask-bootstrap5

Create the Flask app:


from flask import Flask, render_template, redirect, url_for, request, flash
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap5 import Bootstrap
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.config['SECRET_KEY'] = 'supersecretkey'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///event_management.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
Bootstrap(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))
# Create database tables
with app.app_context():
    db.create_all()

3. Flask Routes and Views

Implement routes for authentication, event management, and attendee registration.


@app.route('/')
def index():
    events = Event.query.all()
    return render_template('index.html', events=events)
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        user = User.query.filter_by(username=username).first()
        if user and check_password_hash(user.password_hash, password):
            login_user(user)
            return redirect(url_for('index'))
        flash('Invalid username or password')
    return render_template('login.html')
@app.route('/logout')
@login_required
def logout():
    logout_user()
    return redirect(url_for('index'))
@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        email = request.form['email']
        password = request.form['password']
        role = request.form['role']
        hashed_password = generate_password_hash(password)
        new_user = User(username=username, email=email, password_hash=hashed_password, role=role)
        db.session.add(new_user)
        db.session.commit()
        flash('Registration successful! You can now log in.')
        return redirect(url_for('login'))
    return render_template('register.html')
@app.route('/events')
def events():
    events = Event.query.all()
    return render_template('events.html', events=events)
@app.route('/event/<int:id>', methods=['GET', 'POST'])
def event_detail(id):
    event = Event.query.get_or_404(id)
    if request.method == 'POST':
        if current_user.is_authenticated:
            if len(event.attendees) < event.capacity:
                new_attendance = Attendance(user_id=current_user.id, event_id=event.id)
                db.session.add(new_attendance)
                db.session.commit()
                flash('You have successfully registered for the event!')
            else:
                flash('Event is fully booked.')
            return redirect(url_for('event_detail', id=event.id))
        else:
            flash('You need to log in to register for events.')
            return redirect(url_for('login'))
    return render_template('event_detail.html', event=event)
@app.route('/organizer/events')
@login_required
def organizer_events():
    if current_user.role != 'Organizer':
        flash('Access denied.')
        return redirect(url_for('index'))
    events = Event.query.filter_by(organizer_id=current_user.id).all()
    return render_template('organizer_events.html', events=events)
@app.route('/organizer/event/new', methods=['GET', 'POST'])
@login_required
def new_event():
    if current_user.role != 'Organizer':
        flash('Access denied.')
        return redirect(url_for('index'))
    if request.method == 'POST':
        name = request.form['name']
        description = request.form['description']
        date = request.form['date']
        location = request.form['location']
        capacity = request.form['capacity']
        category_id = request.form['category']
        new_event = Event(name=name, description=description, date=date, location=location, capacity=capacity, organizer_id=current_user.id, category_id=category_id)
        db.session.add(new_event)
        db.session.commit()
        flash('Event created successfully!')
        return redirect(url_for('organizer_events'))
    categories = EventCategory.query.all()
    return render_template('new_event.html', categories=categories)
if __name__ == '__main__':
    app.run(debug=True)

5. HTML Templates

templates/base.html


<!DOCTYPE html>
<html lang=`en`>
<head>
    <meta charset=`UTF-8`>
    <meta name=`viewport` content=`width=device-width, initial-scale=1.0`>
    <link rel=`stylesheet` href=`https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css`>
    <title>{% block title %}Event Management System{% endblock %}</title>
</head>
<body>
    <nav class=`navbar navbar-expand-lg navbar-light bg-light`>
        <div class=`container-fluid`>
            <a class=`navbar-brand` href=`{{ url_for('index') }}`>Event Management</a>
            <div class=`collapse navbar-collapse`>
                <ul class=`navbar-nav me-auto`>
                    <li class=`nav-item`>
                        <a class=`nav-link` href=`{{ url_for('events') }}`>Events</a>
                    </li>
                    <li class=`nav-item`>
                        <a class=`nav-link` href=`{{ url_for('login') }}`>Login</a>
                    </li>
                    <li class=`nav-item`>
                        <a class=`nav-link` href=`{{ url_for('register') }}`>Register</a>
                    </li>
                    <li class=`nav-item`>
                        <a class=`nav-link` href=`{{ url_for('logout') }}`>Logout</a>
                    </li>
                    <li class=`nav-item`>
                        <a class=`nav-link` href=`{{ url_for('organizer_events') }}`>My Events</a>
                    </li>
                </ul>
            </div>
        </div>
    </nav>
    <div class=`container mt-4`>
        {% with messages = get_flashed_messages() %}
            {% if messages %}
                <div class=`alert alert-info`>
                    {% for message in messages %}
                        <p>{{ message }}</p>
                    {% endfor %}
                </div>
            {% endif %}
        {% endwith %}
        {% block content %}{% endblock %}
    </div>
</body>
</html>

templates/index.html


{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to the Event Management System</h1>
<p>Discover and register for exciting events!</p>
<a href=`{{ url_for('events') }}` class=`btn btn-primary`>View Events</a>
{% endblock %}

templates/login.html


{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h1>Login</h1>
<form method=`POST`>
    <div class=`mb-3`>
        <label for=`username` class=`form-label`>Username</label>
        <input type=`text` class=`form-control` id=`username` name=`username` required>
    </div>
    <div class=`mb-3`>
        <label for=`password` class=`form-label`>Password</label>
        <input type=`password` class=`form-control` id=`password` name=`password` required>
    </div>
    <button type=`submit` class=`btn btn-primary`>Login</button>
</form>
{% endblock %}

templates/register.html


{% extends 'base.html' %}
{% block title %}Register{% endblock %}
{% block content %}
<h1>Register</h1>
<form method=`POST`>
    <div class=`mb-3`>
        <label for=`username` class=`form-label`>Username</label>
        <input type=`text` class=`form-control` id=`username` name=`username` required>
    </div>
    <div class=`mb-3`>
        <label for=`email` class=`form-label`>Email</label>
        <input type=`email` class=`form-control` id=`email` name=`email` required>
    </div>
    <div class=`mb-3`>
        <label for=`password` class=`form-label`>Password</label>
        <input type=`password` class=`form-control` id=`password` name=`password` required>
    </div>
    <button type=`submit` class=`btn btn-primary`>Register</button>
</form>
{% endblock %}

templates/dashboard.html


{% extends 'base.html' %}
{% block title %}Dashboard{% endblock %}
{% block content %}
<h2>Dashboard</h2>
<p>Welcome, {{ current_user.username }}!</p>
{% endblock %}

templates/add_expense.html


{% extends 'base.html' %}
{% block title %}Add Expense{% endblock %}
{% block content %}
<h2>Add Expense</h2>
<form method=`POST`>
    {{ form.hidden_tag() }}
    <div class=`mb-3`>
        {{ form.amount.label(class=`form-label`) }}
        {{ form.amount(class=`form-control`) }}
    </div>
    <div class=`mb-3`>
        {{ form.description.label(class=`form-label`) }}
        {{ form.description(class=`form-control`) }}
    </div>
    <div class=`mb-3`>
        {{ form.category.label(class=`form-label`) }}
        {{ form.category(class=`form-control`) }}
    </div>
    <button type=`submit` class=`btn btn-primary`>Add Expense</button>
</form>
{% endblock %}

templates/view_expenses.html


{% extends 'base.html' %}
{% block title %}View Expenses{% endblock %}
{% block content %}
<h2>Your Expenses</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Date</th>
            <th scope=`col`>Description</th>
            <th scope=`col`>Amount</th>
            <th scope=`col`>Category</th>
        </tr>
    </thead>
    <tbody>
        {% for expense in expenses %}
        <tr>
            <td>{{ expense.date.strftime('%Y-%m-%d') }}</td>
            <td>{{ expense.description }}</td>
            <td>${{ expense.amount }}</td>
            <td>{{ expense.category.name }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

templates/add_category.html


{% extends 'base.html' %}
{% block title %}Add Category{% endblock %}
{% block content %}
<h2>Add Category</h2>
<form method=`POST`>
    {{ form.hidden_tag() }}
    <div class=`mb-3`>
        {{ form.name.label(class=`form-label`) }}
        {{ form.name(class=`form-control`) }}
    </div>
    <button type=`submit` class=`btn btn-primary`>Add Category</button>
</form>
{% endblock %}

6. Forms for Flask-WTF


forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, FloatField, TextAreaField, SelectField, SubmitField
from wtforms.validators import DataRequired, Length, Email, EqualTo
class LoginForm(FlaskForm):
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    submit = SubmitField('Login')
class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired(), Length(min=2, max=50)])
    email = StringField('Email', validators=[DataRequired(), Email()])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password', validators=[DataRequired(), EqualTo('password')])
    submit = SubmitField('Register')
class ExpenseForm(FlaskForm):
    amount = FloatField('Amount', validators=[DataRequired()])
    description = TextAreaField('Description', validators=[DataRequired()])
    category = SelectField('Category', coerce=int)
    submit = SubmitField('Add Expense')
class CategoryForm(FlaskForm):
    name = StringField('Category Name', validators=[DataRequired()])
    submit = SubmitField('Add Category')

7. Static Files

static/css/styles.css


body {
    background-color: #f8f9fa;
}
.navbar {
    margin-bottom: 20px;
}
.table {
    margin-top: 20px;
}

8. JavaScript (if needed)

static/js/scripts.js


// Custom JavaScript can be added here

9. Running the Application

To run the application, ensure you have the required packages installed as specified in requirements.txt, then execute:


python run.py

This structure and code provide a comprehensive foundation for an advanced Expense Tracker App using Flask and Bootstrap 5, allowing for user authentication, expense management, and category organization.

Written by Surfside Media

Senior Full Stack Developer specializing in Web Technologies.