Flask Projects With Source Code

Library Management System Project In Flask


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

1. Database Structure

The database will store books, authors, publishers, borrowers, loans, and other related data. We'll use SQLAlchemy (an ORM for Flask) to manage the database.

Database Models


from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
db = SQLAlchemy()
class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)
    publisher_id = db.Column(db.Integer, db.ForeignKey('publisher.id'), nullable=False)
    publication_date = db.Column(db.DateTime, nullable=False)
    loans = db.relationship('Loan', backref='book', lazy=True)
class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    books = db.relationship('Book', backref='author', lazy=True)
class Publisher(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    books = db.relationship('Book', backref='publisher', lazy=True)
class Borrower(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100), nullable=False)
    email = db.Column(db.String(100), nullable=False)
    loans = db.relationship('Loan', backref='borrower', lazy=True)
class Loan(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    book_id = db.Column(db.Integer, db.ForeignKey('book.id'), nullable=False)
    borrower_id = db.Column(db.Integer, db.ForeignKey('borrower.id'), nullable=False)
    loan_date = db.Column(db.DateTime, nullable=False)
    return_date = db.Column(db.DateTime, nullable=False)

2. Flask Application Structure

Organize the project into the following structure:


library_management_system/
│
├── app/
│   ├── __init__.py
│   ├── models.py
│   ├── routes/
│   │   ├── books.py
│   │   ├── authors.py
│   │   ├── publishers.py
│   │   ├── borrowers.py
│   │   ├── loans.py
│   │   └── main.py
│   ├── templates/
│   │   ├── base.html
│   │   ├── index.html
│   │   ├── login.html
│   │   ├── register.html
│   │   ├── dashboard.html
│   │   ├── add_book.html
│   │   ├── add_author.html
│   │   ├── add_publisher.html
│   │   ├── add_borrower.html
│   │   ├── add_loan.html
│   │   └── view_loans.html
│   ├── static/
│   │   ├── css/
│   │   │   └── styles.css
│   │   └── js/
│   │       └── scripts.js
│   └── utils.py
│
├── config.py
├── requirements.txt
└── run.py

3. Flask Application Code

app/__init__.py


from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
login_manager = LoginManager()
def create_app():
    app = Flask(__name__)
    app.config.from_pyfile('config.py')
    db.init_app(app)
    login_manager.init_app(app)
    login_manager.login_view = 'auth.login'
    from .routes.books import books_bp
    from .routes.authors import authors_bp
    from .routes.publishers import publishers_bp
    from .routes.borrowers import borrowers_bp
    from .routes.loans import loans_bp
    from .routes.main import main_bp
    app.register_blueprint(books_bp)
    app.register_blueprint(authors_bp)
    app.register_blueprint(publishers_bp)
    app.register_blueprint(borrowers_bp)
    app.register_blueprint(loans_bp)
    app.register_blueprint(main_bp)
    return app

config.py


import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'your-secret-key'
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 
        'sqlite:///' + os.path.join(basedir, 'library_management_system.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    

run.py


from app import create_app, db
app = create_app()
if __name__ == '__main__':
    with app.app_context():
        db.create_all()
    app.run(debug=True)

4. Flask Routes

routes/books.py


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_required
from ..models import Book, Author, Publisher, db
from ..forms import BookForm
books_bp = Blueprint('books', __name__)
@books_bp.route('/add_book', methods=['GET', 'POST'])
@login_required
def add_book():
    form = BookForm()
    form.author.choices = [(a.id, a.name) for a in Author.query.all()]
    form.publisher.choices = [(p.id, p.name) for p in Publisher.query.all()]
    if form.validate_on_submit():
        book = Book(title=form.title.data, author_id=form.author.data, publisher_id=form.publisher.data, publication_date=form.publication_date.data)
        db.session.add(book)
        db.session.commit()
        flash('Book added successfully!')
        return redirect(url_for('main.dashboard'))
    return render_template('add_book.html', form=form)
@books_bp.route('/books')
@login_required
def view_books():
    books = Book.query.all()
    return render_template('view_books.html', books=books)

routes/authors.py


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_required
from ..models import Author, db
from ..forms import AuthorForm
authors_bp = Blueprint('authors', __name__)
@authors_bp.route('/add_author', methods=['GET', 'POST'])
@login_required
def add_author():
    form = AuthorForm()
    if form.validate_on_submit():
        author = Author(name=form.name.data)
        db.session.add(author)
        db.session.commit()
        flash('Author added successfully!')
        return redirect(url_for('main.dashboard'))
    return render_template('add_author.html', form=form)
@authors_bp.route('/authors')
@login_required
def view_authors():
    authors = Author.query.all()
    return render_template('view_authors.html', authors=authors)
    

routes/publishers.py


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_required
from ..models import Publisher, db
from ..forms import PublisherForm
publishers_bp = Blueprint('publishers', __name__)
@publishers_bp.route('/add_publisher', methods=['GET', 'POST'])
@login_required
def add_publisher():
    form = PublisherForm()
    if form.validate_on_submit():
        publisher = Publisher(name=form.name.data)
        db.session.add(publisher)
        db.session.commit()
        flash('Publisher added successfully!')
        return redirect(url_for('main.dashboard'))
    return render_template('add_publisher.html', form=form)
@publishers_bp.route('/publishers')
@login_required
def view_publishers():
    publishers = Publisher.query.all()
    return render_template('view_publishers.html', publishers=publishers)
    

routes/borrowers.py


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_required
from ..models import Borrower, db
from ..forms import BorrowerForm
borrowers_bp = Blueprint('borrowers', __name__)
@borrowers_bp.route('/add_borrower', methods=['GET', 'POST'])
@login_required
def add_borrower():
    form = BorrowerForm()
    if form.validate_on_submit():
        borrower = Borrower(name=form.name.data, email=form.email.data)
        db.session.add(borrower)
        db.session.commit()
        flash('Borrower added successfully!')
        return redirect(url_for('main.dashboard'))
    return render_template('add_borrower.html', form=form)
@borrowers_bp.route('/borrowers')
@login_required
def view_borrowers():
    borrowers = Borrower.query.all()
    return render_template('view_borrowers.html', borrowers=borrowers)

routes/loans.py


from flask import Blueprint, render_template, redirect, url_for, flash
from flask_login import login_required
from ..models import Loan, Book, Borrower, db
from ..forms import LoanForm
loans_bp = Blueprint('loans', __name__)
@loans_bp.route('/add_loan', methods=['GET', 'POST'])
@login_required
def add_loan():
    form = LoanForm()
    form.book.choices = [(b.id, b.title) for b in Book.query.all()]
    form.borrower.choices = [(br.id, br.name) for br in Borrower.query.all()]
    if form.validate_on_submit():
        loan = Loan(book_id=form.book.data, borrower_id=form.borrower.data, loan_date=form.loan_date.data, return_date=form.return_date.data)
        db.session.add(loan)
        db.session.commit()
        flash('Loan added successfully!')
        return redirect(url_for('main.dashboard'))
    return render_template('add_loan.html', form=form)
@loans_bp.route('/loans')
@login_required
def view_loans():
    loans = Loan.query.all()
    return render_template('view_loans.html', loans=loans)

routes/main.py


from flask import Blueprint, render_template
from flask_login import login_required
main_bp = Blueprint('main', __name__)
@main_bp.route('/')
def index():
    return render_template('index.html')
@main_bp.route('/dashboard')
@login_required
def dashboard():
    return render_template('dashboard.html')

5. HTML Templates with Bootstrap 5

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 href=`https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css` rel=`stylesheet`>
    <link rel=`stylesheet` href=`{{ url_for('static', filename='css/styles.css') }}`>
    <title>{% block title %}Library 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('main.index') }}`>Library Management System</a>
            <div class=`collapse navbar-collapse`>
                <ul class=`navbar-nav me-auto`>
                    {% if current_user.is_authenticated %}
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('main.dashboard') }}`>Dashboard</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('books.view_books') }}`>View Books</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('authors.view_authors') }}`>View Authors</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('publishers.view_publishers') }}`>View Publishers</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('borrowers.view_borrowers') }}`>View Borrowers</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('loans.view_loans') }}`>View Loans</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('auth.logout') }}`>Logout</a>
                        </li>
                    {% else %}
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('auth.login') }}`>Login</a>
                        </li>
                        <li class=`nav-item`>
                            <a class=`nav-link` href=`{{ url_for('auth.register') }}`>Register</a>
                        </li>
                    {% endif %}
                </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>
    <script src=`https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js`></script>
</body>
</html>

templates/index.html


{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome to the Library Management System</h1>
<p>Manage your library efficiently!</p>
{% 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_book.html


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

templates/add_author.html


{% extends 'base.html' %}
{% block title %}Add Author{% endblock %}
{% block content %}
<h2>Add Author</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 Author</button>
</form>
{% endblock %}

templates/add_publisher.html


{% extends 'base.html' %}
{% block title %}Add Publisher{% endblock %}
{% block content %}
<h2>Add Publisher</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 Publisher</button>
</form>
{% endblock %}

templates/add_borrower.html


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

templates/add_loan.html


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

templates/view_books.html


{% extends 'base.html' %}
{% block title %}View Books{% endblock %}
{% block content %}
<h2>Books List</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Title</th>
            <th scope=`col`>Author</th>
            <th scope=`col`>Publisher</th>
            <th scope=`col`>Publication Date</th>
        </tr>
    </thead>
    <tbody>
        {% for book in books %}
        <tr>
            <td>{{ book.title }}</td>
            <td>{{ book.author.name }}</td>
            <td>{{ book.publisher.name }}</td>
            <td>{{ book.publication_date.strftime('%Y-%m-%d') }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

templates/view_authors.html


{% extends 'base.html' %}
{% block title %}View Authors{% endblock %}
{% block content %}
<h2>Authors List</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Name</th>
        </tr>
    </thead>
    <tbody>
        {% for author in authors %}
        <tr>
            <td>{{ author.name }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

templates/view_publishers.html


{% extends 'base.html' %}
{% block title %}View Publishers{% endblock %}
{% block content %}
<h2>Publishers List</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Name</th>
        </tr>
    </thead>
    <tbody>
        {% for publisher in publishers %}
        <tr>
            <td>{{ publisher.name }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

templates/view_borrowers.html


{% extends 'base.html' %}
{% block title %}View Borrowers{% endblock %}
{% block content %}
<h2>Borrowers List</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Name</th>
            <th scope=`col`>Email</th>
        </tr>
    </thead>
    <tbody>
        {% for borrower in borrowers %}
        <tr>
            <td>{{ borrower.name }}</td>
            <td>{{ borrower.email }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}

templates/view_loans.html


{% extends 'base.html' %}
{% block title %}View Loans{% endblock %}
{% block content %}
<h2>Loans List</h2>
<table class=`table`>
    <thead>
        <tr>
            <th scope=`col`>Book</th>
            <th scope=`col`>Borrower</th>
            <th scope=`col`>Loan Date</th>
            <th scope=`col`>Return Date</th>
        </tr>
    </thead>
    <tbody>
        {% for loan in loans %}
        <tr>
            <td>{{ loan.book.title }}</td>
            <td>{{ loan.borrower.name }}</td>
            <td>{{ loan.loan_date.strftime('%Y-%m-%d') }}</td>
            <td>{{ loan.return_date.strftime('%Y-%m-%d') }}</td>
        </tr>
        {% endfor %}
    </tbody>
</table>
{% endblock %}
<h2>6. Forms for Flask-WTF</h2>
<h3>forms.py</h3>
from flask_wtf import FlaskForm
from wtforms import StringField, DateTimeField, SelectField, SubmitField
from wtforms.validators import DataRequired, Email
class BookForm(FlaskForm):
    title = StringField('Title', validators=[DataRequired()])
    author = SelectField('Author', coerce=int, validators=[DataRequired()])
    publisher = SelectField('Publisher', coerce=int, validators=[DataRequired()])
    publication_date = DateTimeField('Publication Date', format='%Y-%m-%d', validators=[DataRequired()])
    submit = SubmitField('Add Book')
class AuthorForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    submit = SubmitField('Add Author')
class PublisherForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    submit = SubmitField('Add Publisher')
class BorrowerForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    email = StringField('Email', validators=[DataRequired(), Email()])
    submit = SubmitField('Add Borrower')
class LoanForm(FlaskForm):
    book = SelectField('Book', coerce=int, validators=[DataRequired()])
    borrower = SelectField('Borrower', coerce=int, validators=[DataRequired()])
    loan_date = DateTimeField('Loan Date', format='%Y-%m-%d', validators=[DataRequired()])
    return_date = DateTimeField('Return Date', format='%Y-%m-%d', validators=[DataRequired()])
    submit = SubmitField('Add Loan')

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 Library Management System using Flask and Bootstrap 5, allowing for book management, author management, publisher management, borrower management, and loan tracking functionality.

Written by Surfside Media

Senior Full Stack Developer specializing in Web Technologies.