Creating an advanced-level Online Ticket Booking 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:

Database Structure

The database will include tables for users, events, tickets, bookings, and payments. We'll use SQLAlchemy for ORM.


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)
bookings = db.relationship('Booking', backref='user', 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)
total_tickets = db.Column(db.Integer, nullable=False)
available_tickets = db.Column(db.Integer, nullable=False)
price = db.Column(db.Float, nullable=False)
tickets = db.relationship('Ticket', backref='event', lazy=True)
class Ticket(db.Model):
id = db.Column(db.Integer, primary_key=True)
event_id = db.Column(db.Integer, db.ForeignKey('event.id'), nullable=False)
booking_id = db.Column(db.Integer, db.ForeignKey('booking.id'), nullable=True)
class Booking(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)
booking_date = db.Column(db.DateTime, default=datetime.utcnow)
total_price = db.Column(db.Float, nullable=False)
payment_status = db.Column(db.String(50), nullable=False) # Paid, Pending, Failed
tickets = db.relationship('Ticket', backref='booking', lazy=True)
class Payment(db.Model):
id = db.Column(db.Integer, primary_key=True)
booking_id = db.Column(db.Integer, db.ForeignKey('booking.id'), nullable=False)
amount = db.Column(db.Float, nullable=False)
payment_date = db.Column(db.DateTime, default=datetime.utcnow)
status = db.Column(db.String(50), nullable=False) # Success, Failed

Flask Application Structure

Here’s the directory structure for the project:


online_ticket_booking/

├── app/
│ ├── __init__.py # Initialize the Flask app and database
│ ├── models.py # Database models (User , Event, Ticket, Booking, Payment)
│ ├── routes.py # Application routes and views
│ ├── forms.py # Forms for user input (if using Flask-WTF)
│ ├── 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
│ ├── events.html # Events listing page
│ ├── event_detail.html # Event details page
│ ├── payment.html # Payment page
│ └── portfolio.html # User portfolio page (if applicable)

├── 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

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:///ticket_booking.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()

Routes and Views

Implement routes for authentication, event management, ticket booking, and payment processing.


@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']
hashed_password = generate_password_hash(password)
new_user = User(username=username, email=email, password_hash=hashed_password)
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:
tickets_to_book = request.form['tickets']
total_price = event.price * int(tickets_to_book)
new_booking = Booking(user_id=current_user.id, event_id=event.id, total_price=total_price, payment_status='Pending')
db.session.add(new_booking)
db.session.commit()
for _ in range(int(tickets_to_book)):
new_ticket = Ticket(event_id=event.id, booking_id=new_booking.id)
db.session.add(new_ticket)
event.available_tickets -= int(tickets_to_book)
db.session.commit()
flash('Tickets booked successfully! Proceed to payment.')
return redirect(url_for('payment', booking_id=new_booking.id))
else:
flash('You need to log in to book tickets.')
return redirect(url_for('login'))
return render_template('event_detail.html', event=event)
@app.route('/payment/<int:booking_id>', methods=['GET', 'POST'])
@login_required
def payment(booking_id):
booking = Booking.query.get_or_404(booking_id)
if request.method == 'POST':
# Simulate payment processing
payment_status = 'Success' # In a real application, integrate with a payment gateway
new_payment = Payment(booking_id=booking.id, amount=booking.total_price, status=payment_status)
db.session.add(new_payment)
booking.payment_status = payment_status
db.session.commit()
flash('Payment processed successfully!')
return redirect(url_for('index'))
return render_template('payment.html', booking=booking)
if __name__ == '__main__':
app.run(debug=True)

HTML Templates

Create the following HTML templates using Bootstrap 5 for styling.

1. 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 %}Online Ticket Booking 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') }}">Ticket Booking</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>
</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>

2. index.html


{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to the Online Ticket Booking System</h1>
<p>Find your favorite events and book tickets easily!</p>
<a href="{{ url_for('events') }}" class="btn btn-primary">View Events</a>
{% endblock %}

3. 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 %}

4. 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 %}

5. events.html


{% extends 'base.html' %}
{% block title %}Events{% endblock %}
{% block content %}
<h1>Available Events</h1>
<table class="table">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Date</th>
<th>Location</th>
<th>Available Tickets</th>
<th>Price</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for event in events %}
<tr>
<td>{{ event.id }}</td>
<td>{{ event.name }}</td>
<td>{{ event.date.strftime('%Y-%m-%d %H:%M') }}</td>
<td>{{ event.location }}</td>
<td>{{ event.available_tickets }}</td>
<td>${{ event.price }}</td>
<td>
<a href="{{ url_for('event_detail', id=event.id) }}" class="btn btn-info">Book Tickets</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

6. event_detail.html


{% extends 'base.html' %}
{% block title %}Event Details{% endblock %}
{% block content %}
<h1>{{ event.name }}</h1>
<p>{{ event.description }}</p>
<p>Date: {{ event.date.strftime('%Y-%m-%d %H:%M') }}</p>
<p>Location: {{ event.location }}</p>
<p>Available Tickets: {{ event.available_tickets }}</p>
<p>Price: ${{ event.price }}</p>
<form method="POST">
<div class="mb-3">
<label for="tickets" class="form-label">Number of Tickets</label>
<input type="number" class="form-control" id="tickets" name="tickets" min="1" max="{{ event.available_tickets }}" required>
</div>
<button type="submit" class="btn btn-primary">Book Tickets</button>
</form>
{% endblock %}

7. payment.html


{% extends 'base.html' %}
{% block title %}Payment{% endblock %}
{% block content %}
<h1>Payment for Booking</h1>
<p>Total Amount: ${{ booking.total_price }}</p>
<form method="POST">
<button type="submit" class="btn btn-success">Pay Now</button>
</form>
{% endblock %}

Conclusion

This structure provides a solid foundation for an advanced Online Ticket Booking System using Flask and Bootstrap 5. You can expand upon this by adding features such as user roles, event categories, and more complex payment processing functionalities.