Creating an advanced-level e-commerce website using Flask and Bootstrap 5 involves designing a robust database structure, implementing backend logic, and creating responsive frontend pages. Below is a detailed breakdown of the database structure, Flask application code, and related pages.

1. Database Structure

The database will be designed using SQLAlchemy (ORM for Flask). It will include tables for users, products, orders, categories, and more.

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(50), unique=True, nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
password = db.Column(db.String(200), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
is_admin = db.Column(db.Boolean, default=False)
orders = db.relationship('Order', backref='user', lazy=True)
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text, nullable=False)
price = db.Column(db.Float, nullable=False)
stock = db.Column(db.Integer, nullable=False)
image = db.Column(db.String(200), nullable=False)
category_id = db.Column(db.Integer, db.ForeignKey('category.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
orders = db.relationship('OrderItem', backref='product', lazy=True)
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
products = db.relationship('Product', backref='category', lazy=True)
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
total_amount = db.Column(db.Float, nullable=False)
status = db.Column(db.String(20), default='Pending')
created_at = db.Column(db.DateTime, default=datetime.utcnow)
items = db.relationship('OrderItem', backref='order', lazy=True)
class OrderItem(db.Model):
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, db.ForeignKey('order.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
price = db.Column(db.Float, nullable=False)

Flask Application Structure

Here’s the directory structure for the project:


advanced_ecommerce/

├── app/
│ ├── __init__.py # Initialize the Flask app and database
│ ├── models.py # Database models (User , Product, Order, Category, Attendance)
│ ├── routes.py # Application routes and views
│ ├── forms.py # Forms for user registration, login, product 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
│ ├── product_details.html # Product details page
│ ├── cart.html # Shopping cart page
│ └── checkout.html # Checkout 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 Code

Below is the Flask application code with routes, forms, and database integration.


from flask import Flask, render_template, request, redirect, url_for, flash, session
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_secret_key'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ecommerce.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
# User Registration
@app.route('/register', methods=['GET', 'POST'])
def register():
if request.method == 'POST':
username = request.form['username']
email = request.form['email']
password = generate_password_hash(request.form['password'], method='sha256')
new_user = User(username=username, email=email, password=password)
db.session.add(new_user)
db.session.commit()
flash('Registration successful! Please log in.', 'success')
return redirect(url_for('login'))
return render_template('register.html')
# User Login
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
email = request.form['email']
password = request.form['password']
user = User.query.filter_by(email=email).first()
if user and check_password_hash(user.password, password):
session['user_id'] = user.id
session['username'] = user.username
flash('Login successful!', 'success')
return redirect(url_for('home'))
else:
flash('Invalid email or password.', 'danger')
return render_template('login.html')
# Home Page
@app.route('/')
def home():
products = Product.query.all()
return render_template('home.html', products=products)
# Product Details
@app.route('/product/<int:id>')
def product_details(id):
product = Product.query.get_or_404(id)
return render_template('product_details.html', product=product)
# Add to Cart
@app.route('/add_to_cart/<int:product_id>', methods=['POST'])
def add_to_cart(product_id):
quantity = request.form.get('quantity', 1, type=int)
cart = session.get('cart', {})
if product_id in cart:
cart[product_id] += quantity
else:
cart[product_id] = quantity
session['cart'] = cart
flash('Product added to cart!', 'success')
return redirect(url_for('home'))
# View Cart
@app.route('/cart')
def view_cart():
cart = session.get('cart', {})
products = Product.query.filter(Product.id.in_(cart.keys())).all()
return render_template('cart.html', products=products, cart=cart)
# Checkout
@app.route('/checkout', methods=['GET', 'POST'])
def checkout():
if request.method == 'POST':
total_amount = sum(Product.query.get(int(id)).price * qty for id, qty in session.get('cart', {}).items())
new_order = Order(user_id=session['user_id'], total_amount=total_amount)
db.session.add(new_order)
db.session.commit()
for product_id, quantity in session['cart'].items():
order_item = OrderItem(order_id=new_order.id, product_id=product_id, quantity=quantity, price=Product.query.get(product_id).price)
db.session.add(order_item)
db.session.commit()
session.pop('cart', None)
flash('Order placed successfully!', 'success')
return redirect(url_for('home'))
return render_template('checkout.html')
# User Logout
@app.route('/logout')
def logout():
session.pop('user_id', None)
session.pop('username', None)
flash('You have been logged out.', 'success')
return redirect(url_for('home'))
if __name__ == '__main__':
with app.app_context():
db.create_all()
app.run(debug=True)

6. HTML Templates

1. templates/register.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Register</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Register</h2>
<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>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

2. templates/login.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Login</title>
</head>
<body>
<div class="container">
<h2 class="mt-5">Login</h2>
<form method="POST">
<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">Login</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

3. templates/home.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Home</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">E-Commerce</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/register">Register</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>Products</h2>
<div class="row">
{% for product in products %}
<div class="col-md-4">
<div class="card mb-4">
<img src="{{ product.image }}" class="card-img-top" alt="{{ product.name }}">
<div class="card-body">
<h5 class="card-title">{{ product.name }}</h5>
<p class="card-text">${{ product.price }}</p>
<form action="{{ url_for('add_to_cart', product_id=product.id) }}" method="POST">
<input type="number" name="quantity" value="1" min="1" class="form-control mb-2">
<button type="submit" class="btn btn-primary">Add to Cart</button>
</form>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

4. templates/product_details.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>{{ product.name }}</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">E-Commerce</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/register">Register</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>{{ product.name }}</h2>
<img src="{{ product.image }}" class="img-fluid" alt="{{ product.name }}">
<p class="mt-3">{{ product.description }}</p>
<h4>${{ product.price }}</h4>
<form action="{{ url_for('add_to_cart', product_id=product.id) }}" method="POST">
<input type="number" name="quantity" value="1" min="1" class="form-control mb-2">
<button type="submit" class="btn btn-primary">Add to Cart</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

5. templates/cart.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Your Cart</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">E-Commerce</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/register">Register</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>Your Cart</h2>
{% if products %}
<table class="table">
<thead>
<tr>
<th>Product</th>
<th>Quantity</th>
<th>Price</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for product in products %}
<tr>
<td>{{ product.name }}</td>
<td>{{ cart[product.id] }}</td>
<td>${{ product.price }}</td>
<td>${{ product.price * cart[product.id] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h4>Total: ${{ total }}</h4>
<a href="/checkout" class="btn btn-success">Proceed to Checkout</a>
{% else %}
<p>Your cart is empty.</p>
{% endif %}
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

6. templates/checkout.html


<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
<title>Checkout</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<a class="navbar-brand" href="/">E-Commerce</a>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="/cart">Cart</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/login">Login</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/register">Register</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container mt-5">
<h2>Checkout</h2>
<form method="POST">
<div class="mb-3">
<label for="address" class="form-label">Shipping Address</label>
<textarea class="form-control" id="address" name="address" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Place Order</button>
</form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>

Conclusion

This structure provides a solid foundation for an advanced e-commerce website using Flask and Bootstrap 5. You can further enhance the application by integrating payment gateways, implementing product reviews, and adding more features based on user feedback. The modular design allows for easy expansion and maintenance, making it a suitable choice for both beginners and experienced developers.