基于flask与数据库的图书管理系统开发
一、开发环境简介
该图书管理系统基于python语言,利用splite3小型数据库,结合sql数据库存储的数据,通过Visual Studio Code编辑器,在flask框架下调用style.css样式,创建网页模板。 在创建数据库表后,利用flask中的辅助方法,完成对数据库的连接,初始化,插入,删除,和查询等操作。与此同时,利用视图函数和网页模板相连接,实现对网页页面的连接操作。
二、系统实现功能模块图
a.注册模块
在此模块下的用户通过提示信息进行注册,在完成用户名以及密码设置后即可登陆系统,后期学院以及学号、邮箱信息可以通过个人或者管理员登陆进行修改,进而使用本系统进行后续的操作。
b.登陆模块
在此模块下设置了不同的权限管理,通过选择不同的登陆方式从而进入不同的环境,如用户登陆以及管理员登陆,对应可以完成不同的操作与功能。
c.管理员模块
如若选择的是管理员身份进行操作,可以在系统中有查看、添加、删除、修改图书信息,也可以对用户信息进行查看,实现修改信息和注销用户,同时在读者还书后实时更新图书归还状态。
d.用户模块
如若选择是用户登陆,可以进行个人信息修改、完善,同时也可以查阅图书信息,依据书名以及作者信息进行检索图书,借阅图书,同时查看自己的阅读记录。
三、代码设计实现
import time
from datetime import datetime
#日期相关操作,和time包连用表示、计算借还书日期
from sqlite3 import dbapi2 as sqlite3
#使用SQLite时,它的功能直接被集成在其中,应用会直接访问包含数据的文件,
#SQLITE功能简约,小型化,追求最大磁盘效率;MYSQL功能全面,综合化,追求最大并发效率。如果只是单机上用的,数据量不是很大,
# 需要方便移植或者需要频繁读/写磁盘文件的话,就用SQLite比较合适;如果是要满足多用户同时访问,或者是网站访问量比较大是使用MYSQL比较合适.
from flask import Flask, request, session, url_for, redirect, render_template, abort, g, flash, _app_ctx_stack
from hashlib import md5
#这是加密函数,将传进来的函数加密
from werkzeug import check_password_hash, generate_password_hash
#数据库中直接存放明文密码是很危险的,Werkzeug库中的security能够方便的实现散列密码的计算
#security库中 generate_password_hash(password,method...)函数将原始密码作为输入,以字符串形式输出密码的散列值
#check_password_hash(hash,password)函数检查给出的hash密码与明文密码是否相符
#CONFIGURATION
DATABASE = 'book.db'
DEBUG = True
SECRET_KEY = 'development key'
MANAGER_NAME = 'admin'
MANAGER_PWD = '123456'
# create our little application :
app = Flask(__name__) #app是Flask的实例,它接收包或者模块的名字作为参数
app.config.from_object(__name__)
#设置一个名为 FLASKR_SETTINGS 环境变量来设定一个配置文件载入后是否覆盖默认值。
#静默开关告诉 Flask 不去关心这个环境变量键值是否存在。
app.config.from_envvar('FLASKR_SETTINGS', silent=True)
#数据库连接
def get_db():
top = _app_ctx_stack.top
#判断top中是否有sqlite_db , 如果top中不包含sqlite_db属性,通过SQLite创建一个简单的数据库连接并通过sqlite.Row对象来表示行。这样就可以将行看作是字典而不是元组。
if not hasattr(top, 'sqlite_db'):
top.sqlite_db = sqlite3.connect(app.config['DATABASE'])
top.sqlite_db.row_factory = sqlite3.Row
return top.sqlite_db
#这个装饰器的作用就是向请求上下文中注册一个函数,当上下文销毁时调用,实际上是一次请求完成后执行
@app.teardown_appcontext
def close_database(exception):
top = _app_ctx_stack.top
#如果top中包含sqlite_db属性,则关闭数据库
if hasattr(top, 'sqlite_db'):
top.sqlite_db.close()
#初始化数据库
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('book.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
#访问数据库
def query_db(query, args=(), one=False):
cur = get_db().execute(query, args)
rv = cur.fetchall()
return (rv[0] if rv else None) if one else rv
#通过用户名(设置唯一,不可重名)给读者id
def get_user_id(username):
rv = query_db('select user_id from users where user_name = ?', [username], one=True)
return rv[0] if rv else None
@app.before_request #此装饰函数会在请求前调用,它没有参 数
def before_request():
g.user = None
if 'user_id' in session:
g.user = session['user_id']
@app.route('/') #在本地服务器上运行网页主页文件
def index():
return render_template('index.html')
@app.route('/manager_login', methods=['GET', 'POST']) #运行manager_login网页文件,方法为POST , GET
def manager_login(): #管理员登陆
error = None
#判断输入的管理员账号和密码是否正确
if request.method == 'POST':
if request.form['username'] != app.config['MANAGER_NAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['MANAGER_PWD']:
error = 'Invalid password'
else:
session['user_id'] = app.config['MANAGER_NAME']
return redirect(url_for('manager'))
return render_template('manager_login.html', error = error)
#读者登录
@app.route('/reader_login', methods=['GET', 'POST'])
def reader_login():
error = None
if request.method == 'POST':
user = query_db('''select * from users where user_name = ?''', #在服务器中查询所输入的名称
[request.form['username']], one=True)
if user is None: #判断用户名是否为空
error = 'Invalid username'
elif not check_password_hash(user['pwd'], request.