Python基于mysql+Django框架图书管理系统源代码(含mysql文件)

项目前台和后台界面模板都是自己编写,前台采用Bootstrap框架UI,后台EasyUI框架UI,没有采用Django自动生成的那个后台管理,因为那个后台实在是太丑了,丑得惨不忍睹!整个项目主要负责图书信息的添加,修改,多个条件组合查询,删除。虽然系统功能不是很复杂,不过这是一个很好的学习案例,包括了常用字段的设计,比如字符串,浮点型,整型,日期型,图片型,富文本字符串型,文件型和下拉框外键关联型,囊括了所有商业项目设计需要的字段类型,通杀所有商业系统设计原理!当然也是学习的不二选择,好东西值得分享,强烈推荐.后台登录用户名密码均为a。
系统实体对象:
图书类型:图书类别,类别名称,可借阅天数
图书:图书条形码,图书名称,图书所在类别,图书价格,库存,出版日期,出版社,图书图片,图书简介,图书文件。
程序运行截图
在这里插入图片描述
在这里插入图片描述
核心代码

"""
Django settings for PythonProject project.

Generated by 'django-admin startproject' using Django 2.2.5.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os
import sys

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

#sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'fav!(r-3=i+bya!meg=vw*zcn-$4g3vhav!!)mw=f!b)7+7it2'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'apps.Index', #首页模块
    'apps.BookType', #图书分类模块
    'apps.Book', #图书信息模块

    'tinymce', #富文本编辑器
]

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',
]

ROOT_URLCONF = 'PythonProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'PythonProject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'db_book',
        'USER': 'root',
        'PASSWORD': 'sxing86',
        'HOST': '127.0.0.1',
        'PORT': 3306,
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'
STATICFILES_DIRS = [ os.path.join(BASE_DIR, 'static') ]


MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace("\\", "/")
MEDIA_URL = '/media/'



# 配置session存储
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

#富文本编辑器配置
TINYMCE_DEFAULT_CONFIG = {
    'theme': 'simple',
    'width': '100%',
    'height': '300px',
}

BookType/views.py

from django.views.generic import View
from django.shortcuts import render
from apps.BookType.models import BookType
from django.core.paginator import Paginator
from django.http import JsonResponse


class FrontAddView(View):
    def get(self,request):
        pass

    def post(self,request):
        pass

class ListAllView(View):
    def get(self,request):
        bookTypes = BookType.objects.all()
        bookTypeList = []
        for bookType in bookTypes:
            bookTypeObj = {
                'bookTypeId': bookType.bookTypeId,
                'bookTypeName': bookType.bookTypeName,
            }
            bookTypeList.append(bookTypeObj)
        return JsonResponse(bookTypeList,safe=False)


class FrontListView(View):
    def get(self,request):
        pageSize = 5
        currentPage = request.GET.get("currentPage")
        bookTypes = BookType.objects.all()
        paginator = Paginator(bookTypes, pageSize)
        totalPage = paginator.num_pages
        recordNumber = paginator.count

        # 获取第page页的内容
        try:
            currentPage = int(currentPage)
        except Exception as e:
            currentPage = 1
        if currentPage > totalPage:
            currentPage = totalPage

        # 获取第page页的Page实例对象
        bookTypes_page = paginator.page(currentPage)

        startIndex = (currentPage - 1) * pageSize #计算起始序号


        startPage = currentPage - 5
        endPage = currentPage + 5
        if startPage < 1:
            startPage=1
        if endPage > totalPage:
            endPage = totalPage;

        pageList = list(range(startPage,endPage+1))

        context = {
            'bookTypes_page': bookTypes_page,
            'currentPage': currentPage,
            'totalPage': totalPage,
            'recordNumber': recordNumber,
            'startIndex': startIndex,
            'pageList': pageList,
        }

        print(pageList)

        # 使用模板
        return render(request, 'BookType/bookType_frontquery_result.html', context)


    def post(self,request):
        pass

Book/views.py

from django.views.generic import View
from apps.BaseView import BaseView
from django.shortcuts import render
from django.core.paginator import Paginator
from apps.Book.models import Book
from apps.BookType.models import BookType
from django.http import JsonResponse
from django.http import FileResponse
from apps.BaseView import ImageFormatException
from django.conf import settings
import pandas as pd
import os


class FrontAddView(BaseView):  # 前台图书添加
    def primaryKeyExist(self, barcode):  # 判断主键是否存在
        try:
            Book.objects.get(barcode=barcode)
            return True
        except Book.DoesNotExist:
            return False

    def get(self,request):
        bookTypes = BookType.objects.all()  # 获取所有图书类型
        context = {
            'bookTypes': bookTypes,
        }
        # 使用模板
        return render(request, 'Book/book_frontAdd.html', context)

    def post(self,request):
        barcode = request.POST.get('book.barcode') # 判断图书条形码是否存在
        if self.primaryKeyExist(barcode):
            return JsonResponse({'success': False, 'message': '图书条形码已经存在'})

        book = Book() # 新建一个图书对象然后获取参数
        book.barcode = barcode
        book.bookName = request.POST.get('book.bookName')
        book.bookTypeObj = BookType.objects.get(bookTypeId=int(request.POST.get('book.bookTypeObj.bookTypeId')))
        book.price = float(request.POST.get('book.price'))
        book.count = int(request.POST.get('book.count'))
        book.publishDate = request.POST.get('book.publishDate')
        book.publish = request.POST.get('book.publish')
        try:
            book.bookPhoto = self.uploadImageFile(request,'book.bookPhoto')
        except ImageFormatException as ife:
            return JsonResponse({'success': False, 'message': ife.error})
        book.bookDesc = request.POST.get('book.bookDesc')
        book.bookFile = self.uploadCommonFile(request,'book.bookFile')
        book.save() # 保存图书信息到数据库
        return JsonResponse({'success': True, 'message': '保存成功'})


class FrontModifyView(BaseView):  # 前台修改图书
    def get(self, request, barcode):
        context = {"barcode": barcode}
        return render(request, 'Book/book_frontModify.html', context)


class FrontListView(BaseView):  # 前台图书查询列表
    def get(self, request):
        return self.handle(request)

    def post(self, request):
        return self.handle(request)

    def handle(self,request):
        self.getCurrentPage(request)  # 获取当前要显示第几页
        # 下面获取查询参数
        barcode = self.getStrParam(request, 'barcode')
        bookName = self.getStrParam(request, 'bookName')
        publishDate = self.getStrParam(request, 'publishDate')
        bookTypeObj_bookTypeId = self.getIntParam(request, 'bookTypeObj.bookTypeId')
        # 然后条件组合查询过滤
        book = Book.objects.all()
        if barcode != '':
            book = book.filter(barcode__contains=barcode)
        if bookName != '':
            book = book.filter(bookName__contains=bookName)
        if publishDate != '':
            book = book.filter(publishDate__contains=publishDate)
        if bookTypeObj_bookTypeId != '0':
            book = book.filter(bookTypeObj=bookTypeObj_bookTypeId)
        # 对查询结果利用Paginator进行分页
        self.paginator = Paginator(book, self.pageSize)
        # 计算总的页码数,要显示的页码列表,总记录等
        self.calculatePages()
        # 获取第page页的Page实例对象
        books_page = self.paginator.page(self.currentPage)

        # 获取所有图书类型
        bookTypes = BookType.objects.all()
        # 构造模板需要的参数
        context = {
            'bookTypes': bookTypes,
            'books_page': books_page,
            'barcode': barcode,
            'bookName': bookName,
            'publishDate': publishDate,
            'bookTypeObj_bookTypeId': int(bookTypeObj_bookTypeId),
            'currentPage': self.currentPage,
            'totalPage': self.totalPage,
            'recordNumber': self.recordNumber,
            'startIndex': self.startIndex,
            'pageList': self.pageList,
        }
        # 渲染模板界面
        return render(request, 'Book/book_frontquery_result.html', context)


class FrontShowView(View):  # 前台显示图片详情页
    def get(self, request, barcode):
        bookTypes = BookType.objects.all()
        # 查询需要显示的图书对象
        book = Book.objects.get(barcode=barcode)
        context = {
            'bookTypes': bookTypes,
            'book': book
        }
        # 渲染模板显示
        return render(request, 'Book/book_frontshow.html', context)


class UpdateView(BaseView):  # Ajax方式图书更新
    def get(self, request, barcode):
        # GET方式请求查询图书对象并返回图书json格式
        book = Book.objects.get(barcode=barcode)
        return JsonResponse(book.getJsonObj())

    def post(self, request, barcode):
        # POST方式提交图书修改信息更新到数据库
        book = Book.objects.get(barcode=barcode)
        book.bookName = request.POST.get('book.bookName')
        book.bookTypeObj = BookType.objects.get(bookTypeId=int(request.POST.get('book.bookTypeObj.bookTypeId')))
        book.price = float(request.POST.get('book.price'))
        book.count = int(request.POST.get('book.count'))
        book.publishDate = request.POST.get('book.publishDate')
        book.publish = request.POST.get('book.publish')
        try:
            bookPhotoName = self.uploadImageFile(request, 'book.bookPhoto')
        except ImageFormatException as ife:
            return JsonResponse({'success': False, 'message': ife.error})
        if bookPhotoName != 'img/NoImage.jpg':
            book.bookPhoto = bookPhotoName

        book.bookDesc = request.POST.get('book.bookDesc')
        bookFileName = self.uploadCommonFile(request, 'book.bookFile')
        if bookFileName != 'file/NoFile.jpg':
            book.bookFile = bookFileName

        book.save()
        return JsonResponse({'success': True, 'message': '保存成功'})


class AddView(BaseView):  # 后台添加图书
    def primaryKeyExist(self, barcode):  # 判断主键是否存在
        try:
            Book.objects.get(barcode=barcode)
            return True
        except Book.DoesNotExist:
            return False

    def get(self, request):
        # 获取所有图书类型
        bookTypes = BookType.objects.all()
        context = {
            'bookTypes': bookTypes,
        }
        # 渲染显示模板界面
        return render(request, 'Book/book_add.html', context)

    def post(self, request):
        # POST方式处理图书添加业务
        barcode = request.POST.get('book.barcode')
        if self.primaryKeyExist(barcode):
            return JsonResponse({'success': False, 'message': '图书条形码已经存在'})
        # 新建一个图书对象然后收集图书参数
        book = Book()
        book.barcode = barcode
        book.bookName = request.POST.get('book.bookName')
        book.bookTypeObj = BookType.objects.get(bookTypeId=int(request.POST.get('book.bookTypeObj.bookTypeId')))
        book.price = float(request.POST.get('book.price'))
        book.count = int(request.POST.get('book.count'))
        book.publishDate = request.POST.get('book.publishDate')
        book.publish = request.POST.get('book.publish')
        try:
            book.bookPhoto = self.uploadImageFile(request, 'book.bookPhoto')
        except ImageFormatException as ife:
            return JsonResponse({'success': False, 'message': ife.error})
        book.bookDesc = request.POST.get('book.bookDesc')
        book.bookFile = self.uploadCommonFile(request, 'book.bookFile')
        book.save()  # 这里提交更新到数据库
        return JsonResponse({'success': True, 'message': '保存成功'})


class BackModifyView(BaseView):  # 后台更新图书
    def get(self, request, barcode):
        context = {"barcode": barcode}
        return render(request, 'Book/book_modify.html', context)


class ListView(BaseView):  # 后台图书列表
    def get(self, request):
        # 使用模板
        return render(request, 'Book/book_query_result.html')

    def post(self,request):
        # 获取当前要显示第几页和每页几条数据
        self.getPageAndSize(request)
        # 收集查询参数
        barcode = self.getStrParam(request, 'barcode')
        bookName = self.getStrParam(request, 'bookName')
        publishDate = self.getStrParam(request, 'publishDate')
        bookTypeObj_bookTypeId = self.getIntParam(request, 'bookTypeObj.bookTypeId')
        # 然后条件组合查询过滤
        books = Book.objects.all()
        if barcode != '':
            books = books.filter(barcode__contains=barcode)
        if bookName != '':
            books = books.filter(bookName__contains=bookName)
        if publishDate != '':
            books = books.filter(publishDate__contains=publishDate)
        if bookTypeObj_bookTypeId != '0':
            books = books.filter(bookTypeObj=bookTypeObj_bookTypeId)
        # 利用Paginator对查询结果集分页
        self.paginator = Paginator(books, self.pageSize)
        # 计算总的页码数,要显示的页码列表,总记录等
        self.calculatePages()
        # 获取第page页的Page实例对象
        books_page = self.paginator.page(self.currentPage)
        # 查询的结果集转换为列表
        bookList = []
        for book in books_page:
            book = book.getJsonObj()
            bookList.append(book)
        # 构造模板页面需要的参数
        book_res = {
            'rows': bookList,
            'total': self.recordNumber,
        }
        # 渲染模板页面显示
        return JsonResponse(book_res, json_dumps_params={'ensure_ascii':False})


class DeletesView(BaseView):  # 删除图书信息
    def get(self, request):
        return self.handle(request)

    def post(self, request):
        return self.handle(request)

    def handle(self, request):
        barcodes = self.getStrParam(request, 'barcodes')
        barcodes = barcodes.split(',')
        count = 0
        try:
            for barcode in barcodes:
                Book.objects.get(barcode=barcode).delete()
                count = count + 1
            message = '%s条记录删除成功!' % count
            success = True
        except Exception as e:
            message = '数据库删除发生错误!'
            success = False
        return JsonResponse({"success": success, "message": message})


class OutToExcelView(BaseView):  # 导出图书信息到excel并下载
    def get(self,request):
        # 收集查询参数
        barcode = self.getStrParam(request, 'barcode')
        bookName = self.getStrParam(request, 'bookName')
        publishDate = self.getStrParam(request, 'publishDate')
        bookTypeObj_bookTypeId = self.getIntParam(request, 'bookTypeObj.bookTypeId')
        # 然后条件组合查询过滤
        books = Book.objects.all()
        if barcode != '':
            books = books.filter(barcode__contains=barcode)
        if bookName != '':
            books = books.filter(bookName__contains=bookName)
        if publishDate != '':
            books = books.filter(publishDate__contains=publishDate)
        if bookTypeObj_bookTypeId != '0':
            books = books.filter(bookTypeObj=bookTypeObj_bookTypeId)
        #将查询结果集转换成列表
        bookList = []
        for book in books:
            book = book.getJsonObj()
            bookList.append(book)
        # 利用pandas实现数据的导出功能
        pf = pd.DataFrame(bookList)
        # 设置要导入到excel的列
        columns_map = {
            'barcode': '图书条形码',
            'bookName': '图书名称',
            'bookTypeObj': '图书类别',
            'price': '图书价格',
            'count': '图书数量',
            'publishDate': '出版日期',
            'publish': '出版社',
        }
        pf = pf[columns_map.keys()]
        pf.rename(columns=columns_map, inplace=True)
        # 将空的单元格替换为空字符
        pf.fillna('', inplace=True)
        #设定文件名和导出路径
        filename = 'books.xlsx'
        # 这个路径可以在settings中设置也可以直接手动输入
        root_path = settings.MEDIA_ROOT + '/output/'
        file_path = os.path.join(root_path, filename)
        pf.to_excel(file_path, encoding='utf-8', index=False)
        # 将生成的excel文件输出到网页下载
        file = open(file_path, 'rb')
        response = FileResponse(file)
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename="books.xlsx"'
        return response

完整程序代码下载:Python基于mysql+Django框架图书管理系统源代码(含mysql文件)
更多Python源代码请关注公众号:Python代码大全。在这里插入图片描述

  • 2
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Python代码大全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值