Build a Full-Featured Django Library Management System from Scratch

This tutorial walks you through configuring Django templates, static files, middleware, and MySQL database settings, then defines models for publishers, books, and authors, implements CRUD views and URL routing, and creates the necessary front‑end templates to build a complete library management application.

MaGe Linux Operations
MaGe Linux Operations
MaGe Linux Operations
Build a Full-Featured Django Library Management System from Scratch

Django File Configuration

Django template file configuration

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "template")],  # template folder location
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

Django static file configuration

STATIC_URL = '/static/'  # URL prefix for static files
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static"),  # static file location
]

Disable CSRF middleware temporarily for testing forms

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Django Database Configuration

Switch from the default SQLite to MySQL to simplify development with PyMySQL.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # important to use uppercase keys
        'NAME': 'test_site',
        'HOST': '127.0.0.1',
        'PORT': 3306,
        'USER': 'root',
        'PASSWORD': '',  # leave empty if no password
    }
}

Configure PyMySQL as MySQLdb in

__init__.py
import pymysql
pymysql.install_as_MySQLdb()

Django Core Modules

HttpResponse returns data to the browser.

def index(request):
    # business logic
    return HttpResponse("Hello World")

render fills a template with context data.

def index(request):
    # business logic
    return render(request, "index.html", {"name": "Albert", "hobby": ["音乐", "篮球"]})

redirect performs URL redirection (default 302).

def index(request):
    # business logic
    return redirect("/home/")

To make the redirect permanent, add permanent=True to redirect().

Django Library Management System

Requirements:

Display publisher, book, and author pages.

One publisher can publish many books (one‑to‑many).

One author can write many books and a book can have multiple authors (many‑to‑many).

Create Django Project

Run the following commands in a terminal:

# Django-admin startproject lms
# cd lms
# python3 manage.py startapp app01

Set up the database, modify settings, and define URL routes.

"""lms URL Configuration

The `urlpatterns` list routes URLs to views. For more information see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
"""
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publisher_list/', views.publisher_list),
    url(r'^add_publisher/', views.add_publisher),
    url(r'^drop_publisher/', views.drop_publisher),
    url(r'^edit_publisher/', views.edit_publisher),
    url(r'^book_list/', views.book_list),
    url(r'^add_book/', views.add_book),
    url(r'^drop_book/', views.drop_book),
    url(r'^edit_book/', views.edit_book),
    url(r'^author_list/', views.author_list),
    url(r'^add_author/', views.add_author),
    url(r'^drop_author/', views.drop_author),
    url(r'^edit_author/', views.edit_author),
    url(r'^$', views.publisher_list),  # default route
]

Define Models (app01/models.py)

from django.db import models

# Publisher model
class Publisher(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64)

# Book model
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64)
    publisher = models.ForeignKey(to=Publisher)

# Author model
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=64)
    book = models.ManyToManyField(to=Book)

Views (app01/views.py)

from django.shortcuts import render, redirect
from app01 import models

# Publisher list
def publisher_list(request):
    publisher = models.Publisher.objects.all()
    return render(request, 'publisher_list.html', {'publisher_list': publisher})

# Add publisher
def add_publisher(request):
    if request.method == 'POST':
        new_publisher_name = request.POST.get('name')
        models.Publisher.objects.create(name=new_publisher_name)
        return redirect('/publisher_list/')
    return render(request, 'add_publisher.html')

# Delete publisher
def drop_publisher(request):
    drop_id = request.GET.get('id')
    drop_obj = models.Publisher.objects.get(id=drop_id)
    drop_obj.delete()
    return redirect('/publisher_list/')

# Edit publisher
def edit_publisher(request):
    if request.method == 'POST':
        edit_id = request.GET.get('id')
        edit_obj = models.Publisher.objects.get(id=edit_id)
        new_name = request.POST.get('name')
        edit_obj.name = new_name
        edit_obj.save()
        return redirect('/publisher_list/')
    edit_id = request.GET.get('id')
    edit_obj = models.Publisher.objects.get(id=edit_id)
    return render(request, 'edit_publisher.html', {'publisher': edit_obj})

# Book list
def book_list(request):
    book = models.Book.objects.all()
    return render(request, 'book_list.html', {'book_list': book})

# Add book
def add_book(request):
    if request.method == 'POST':
        new_book_name = request.POST.get('name')
        publisher_id = request.POST.get('publisher_id')
        models.Book.objects.create(name=new_book_name, publisher_id=publisher_id)
        return redirect('/book_list/')
    res = models.Publisher.objects.all()
    return render(request, 'add_book.html', {'publisher_list': res})

# Delete book
def drop_book(request):
    drop_id = request.GET.get('id')
    drop_obj = models.Book.objects.get(id=drop_id)
    drop_obj.delete()
    return redirect('/book_list/')

# Edit book
def edit_book(request):
    if request.method == 'POST':
        new_book_name = request.POST.get('name')
        new_publisher_id = request.POST.get('publisher_id')
        edit_id = request.GET.get('id')
        edit_obj = models.Book.objects.get(id=edit_id)
        edit_obj.name = new_book_name
        edit_obj.publisher_id = new_publisher_id
        edit_obj.save()
        return redirect('/book_list/')
    edit_id = request.GET.get('id')
    edit_obj = models.Book.objects.get(id=edit_id)
    all_publisher = models.Publisher.objects.all()
    return render(request, 'edit_book.html', {'book': edit_obj, 'publisher_list': all_publisher})

# Author list
def author_list(request):
    author = models.Author.objects.all()
    return render(request, 'author_list.html', {'author_list': author})

# Add author
def add_author(request):
    if request.method == 'POST':
        new_author_name = request.POST.get('name')
        models.Author.objects.create(name=new_author_name)
        return redirect('/author_list/')
    return render(request, 'add_author.html')

# Delete author
def drop_author(request):
    drop_id = request.GET.get('id')
    drop_obj = models.Author.objects.get(id=drop_id)
    drop_obj.delete()
    return redirect('/author_list/')

# Edit author
def edit_author(request):
    if request.method == 'POST':
        edit_id = request.GET.get('id')
        edit_obj = models.Author.objects.get(id=edit_id)
        new_author_name = request.POST.get('name')
        new_book_id = request.POST.getlist('book_id')
        edit_obj.name = new_author_name
        edit_obj.book.set(new_book_id)
        edit_obj.save()
        return redirect('/author_list/')
    edit_id = request.GET.get('id')
    edit_obj = models.Author.objects.get(id=edit_id)
    all_book = models.Book.objects.all()
    return render(request, 'edit_author.html', {'author': edit_obj, 'book_list': all_book})

Front‑End Templates

Typical template snippets use Django's template language to loop over querysets and bind data to forms.

<tbody>
    {% for publisher in publisher_list %}
    <tr>
        <td>{{ forloop.counter }}</td>
        <td>{{ publisher.name }}</td>
        <td class="text-center">
            <a class="btn btn-info btn-sm" href="/edit_publisher/?id={{ publisher.id }}"><i class="fa fa-pencil fa-fw" aria-hidden="true"></i>编辑</a>
            <a class="btn btn-danger btn-sm" href="/drop_publisher/?id={{ publisher.id }}"><i class="fa fa-trash-o fa-fw" aria-hidden="true"></i>删除</a>
        </td>
    </tr>
    {% endfor %}
</tbody>

When selecting a publisher for a book, use conditional logic to set the selected option.

<select class="form-control" name="publisher_id">
    {% for publisher in publisher_list %}
        {% if publisher == book.publisher %}
            <option selected value="{{ publisher.id }}">{{ publisher.name }}</option>
        {% else %}
            <option value="{{ publisher.id }}">{{ publisher.name }}</option>
        {% endif %}
    {% endfor %}
</select>

The complete source code is available on GitHub at https://github.com/mayite/lms .

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

databaseBackend DevelopmentDjangoORMWeb Development
MaGe Linux Operations
Written by

MaGe Linux Operations

Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.