文章目录
- 代码实现篇
- 创建数据库
- 代码框架
- 主程序(app.py)
- 扩展(exts.py)
- 主程序用到的方法(methods.py)
- 数据库配置信息(config.py)
- 创建相应数据库模型(models.py)
- 将models中所写模型映射到数据库中(manager.py)
代码实现篇
创建数据库
- 利用命令提示符登录数据库(方法在准备篇,这里不做阐述)
- 创建一个名为db_info的数据库(SQL语句)
create database db_info charset utf8;
代码框架
主程序(app.py)
from flask import Flask, render_template, request, make_response, send_file
from models import Admin, Student, Project
from exts import db
import config, os
from methods import get_Info, to_Data, to_List, to_Json, new_avatar_name, create_xlsx
from flask_cors import *
app = Flask(__name__)
CORS(app, supports_credentials = True) # 解决跨域问题
app.config.from_object(config)
db.init_app(app)
url = "http://127.0.0.1:5000/"
@app.route('/')
def index():
#return render_template('index.html')
return ("首页")
@app.route('/login', methods=['POST']) # 登录
def login():
data = to_Data()
account = data['account']
password = data['password']
if account and password:
admin = Admin.query.filter(Admin.Adminaccount == account, Admin.Password == password).first()
if admin:
return ("1")
return ("0")
@app.route('/by_input', methods = ['POST']) # 按输入查询
def by_input():
data = to_Data() # 将json转为字典
input = data['input']
page = data['page']
if input and page:
info = get_Info(input = input) #从数据库获取成员信息
list = to_List(info, page) #将数据转为列表
data = to_Json(list) #将列表数据转为json
return data
return ("0")
@app.route('/by_name', methods = ['POST']) # 按姓名查询
def by_name():
data = to_Data()
sname = data['name']
page = data['page']
if sname and page:
info = get_Info(sname = sname)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_group', methods = ['POST']) # 按组别查询
def by_group():
data = to_Data()
group = data['group']
page = data['page']
if group and page:
info = get_Info(group = group)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_grade', methods = ['POST']) # 按年级查询
def by_grade():
data = to_Data()
grade = data['grade']
page = data['page']
if grade and page:
info = get_Info(grade = grade)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_name_group', methods=['POST']) # 按姓名、组别查询
def by_name_group():
data = to_Data()
sname = data['name']
group = data['group']
page = data['page']
if sname and group and page:
info = get_Info(sname = sname, group = group)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_name_grade', methods=['POST']) # 按姓名、年级
def by_name_grade():
data = to_Data()
sname = data['name']
grade = data['grade']
page = data['page']
if sname and grade and page:
info = get_Info(sname = sname, grade = grade)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_group_grade', methods=['POST']) # 按组别、年级
def by_group_grade():
data = to_Data()
group = data['group']
grade = data['grade']
page = data['page']
if group and grade and page:
info = get_Info(group = group, grade = grade)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/by_name_group_grade', methods=['POST']) # 按姓名、组别、年级查询
def by_name_group_grade():
data = to_Data()
sname = data['name']
group = data['group']
grade = data['grade']
page = data['page']
if sname and group and grade and page:
info = get_Info(sname = sname, group = group, grade = grade)
list = to_List(info, page)
data = to_Json(list)
return data
return ("0")
@app.route('/up/image', methods=['POST']) # 上传头像
def up_image():
sno = request.form.get('sno')
# sno = "20182109xxxx"
avatar = request.files['image_data'] # 上传图片数据名
if sno and avatar:
student = Student.query.filter(Student.SNo == sno).first() # 查找相应成员
if student:
basedir = os.path.dirname(__file__) # 运行路径
avatar_path = os.path.join(basedir, 'static\image', new_avatar_name(avatar.filename)) # 重命名后合成文件在服务器的路径
avatar_path = avatar_path.replace('\\','/') # 若不换成/ Linux服务器会报错 位置:static/image/*.jpg
avatar.save(avatar_path) # 保存文件
avatar_url = url + avatar_path # 合成头像访问路径
old_url = student.Avatar
if old_url: # 判断是否存在,若存在删除存储的旧头像
old_url = old_url.replace(url,'') # 除去路径中的url
os.remove(old_url)
student.Avatar = avatar_url # 将链接存储在数据库
db.session.add(student)
db.session.commit()
return ("1")
return ("0")
@app.route('/add_change/info', methods=['POST']) # 添加或修改成员数据
def add_change_info():
data = to_Data()
sno = data['sno']
avatar = url + "static/image/0.png" # 默认头像
sname = data['name']
grade = data['grade']
group = data['group']
ID = data['ID'] # 从前端获取得需要修改数据项目的ID列表
state = data['state'] # 添加或修改
data_pro = data['project_arr']
telephone = data['contact']['phone']
wechat = data['contact']['wx']
qq = data['contact']['qq']
mailbox = data['contact']['email']
other = data['contact']['other']
occupation = data['graduation']['job']
workaddress = data['graduation']['address']
direction = data['graduation']['study']
if sno and sname and grade and group:
if state == 0: # 修改
student = Student.query.filter(Student.SNo == sno).first()
# student.SNo = sno # 学号作为主键不可更改
student.SName = sname
student.Group = group
student.Grade = grade
student.Telephone = telephone
student.WeChat = wechat
student.QQ = qq
student.MailBox = mailbox
student.Other = other
student.Occupation = occupation
student.WorkAddress = workaddress
student.Direction = direction
db.session.add(student) # 修改成员数据
db.session.commit() # 提交
for data in data_pro:
if data['ID'] == 0:
project = data['name']
award = data['prize']
code = data['code']
project = Project(SNo=sno, Project=project, Award=award, Code=code)
db.session.add(project) # 添加项目数据
db.session.commit()
if ID:
for id in ID:
project = Project.query.filter(Project.ID == id).first()
if project:
for data in data_pro:
if data['ID'] == id:
project.Project = data['name']
project.Award = data['prize']
project.Code = data['code']
db.session.add(project) # 修改项目数据
db.session.commit()
return ("1")
elif state == 1: # 增加
student = Student.query.filter(Student.SNo == sno).first()
if not student:
student = Student(SNo=sno, Avatar=avatar, SName=sname, Grade=grade, Group=group, Telephone=telephone, WeChat=wechat,
QQ=qq, MailBox=mailbox, Other=other, Occupation=occupation, WorkAddress=workaddress, Direction=direction)
db.session.add(student) # 添加成员数据
db.session.commit() # 提交
for data in data_pro:
project = data['name']
award = data['prize']
code = data['code']
project = Project(SNo=sno, Project=project, Award=award, Code=code)
db.session.add(project) # 添加项目数据
db.session.commit()
return ("1")
return ("0") # 成员已经存在
return ("-1") # 学号、姓名不能为空
@app.route('/delete/info', methods = ['POST']) # 删除成员
def delete_info():
data = to_Data()
sno = data['sno']
if sno:
student = Student.query.filter(Student.SNo == sno).first()
if student:
old_url = student.Avatar
if old_url: # 删除存储在服务器的头像
old_url = old_url.replace(url, '') # 除去路径中的url
os.remove(old_url)
Student.query.filter(Student.SNo == sno).delete() # 删除
db.session.commit()
return ("1")
return ("0")
@app.route('/delete/pro', methods=['POST']) # 删除项目
def delete_pro():
data = to_Data()
ID = data['ID']
if ID:
Project.query.filter(Project.ID == ID).delete()
db.session.commit()
return ("1")
return ("0")
@app.route('/excel')
def excel():
info = Student.query.filter().all()
excel_path = create_xlsx(info)
if excel_path:
response = make_response(send_file(excel_path))
response.headers["Content-Disposition"] = "attachment; filename = {}".format('新思路成员信息一览表.xls'.encode().decode('latin-1'))
# 将文件名(中文)utf-8编码转成 latin-1 编码
return response
return ("0")
if __name__ == '__main__':
# app.run(host = '0.0.0.0', port = 80) # 若要配置在服务器上
app.run()
扩展(exts.py)
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
主程序用到的方法(methods.py)
from flask import request
import json, re, datetime, random, os
from models import Student, Project
from werkzeug.utils import secure_filename
import xlwt # 向excel表格写数据的库
def get_Info(sname = None, group = None, grade = None, input = None):
info = None
if sname:
sname = re.sub(' ', "", sname) # 除去空格
sname = re.sub('\d+', "", sname) # 提取姓名
if sname and group and grade:
info = Student.query.filter(Student.SName == sname, Student.Group == group, Student.Grade == grade).all()
if not info: # 模糊查询
sname = "%" + sname + "%" # 模糊条件
info = Student.query.filter(Student.SName.like(sname)).all()
elif sname and group:
info = Student.query.filter(Student.SName == sname, Student.Group == group).all()
if not info: # 模糊查询
sname = "%" + sname + "%" # 模糊条件
info = Student.query.filter(Student.SName.like(sname)).all()
elif sname and grade:
info = Student.query.filter(Student.SName == sname, Student.Grade == grade).all()
if not info: # 模糊查询
sname = "%" + sname + "%" # 模糊条件
info = Student.query.filter(Student.SName.like(sname)).all()
elif group and grade:
info = Student.query.filter(Student.Group == group, Student.Grade == grade).all()
elif sname:
info = Student.query.filter(Student.SName == sname).all()
if not info: # 模糊查询
sname = "%" + sname + "%" # 模糊条件
info = Student.query.filter(Student.SName.like(sname)).all()
elif group:
info = Student.query.filter(Student.Group == group).all()
elif grade:
info = Student.query.filter(Student.Grade == grade).all()
elif input:
input = re.sub(' ', "", input) # 除去空格
# 输入条件为学号查询
input_sno = re.sub('\D', "", input) # 提取数字
if len(input_sno) > 6:
info = Student.query.filter(Student.SNo == input_sno).all()
if not info:
input_sno = "%" + input_sno + "%"
info = Student.query.filter(Student.SNo.like(input_sno)).all()
if not info:
# 为姓名查询
input_name = re.sub('\d+',"",input) # 提取姓名
if len(input_name) >= 1: # 存在
info = Student.query.filter(Student.SName == input_name).all()
if not info: # 模糊查询
input_name = "%" + input_name + "%"
info = Student.query.filter(Student.SName.like(input_name)).all()
if not info:
# 为组别
input_group = re.sub('\d+', "", input) # 提取组别
if len(input_group) >= 1: # 存在
info = Student.query.filter(Student.Group == input_group).all()
if not info: # 模糊查询
input_group = "%" + input_group +"%"
info = Student.query.filter(Student.Group.like(input_group)).all()
if not info:
# 为年级查询
input_grade = re.sub('\D',"",input) # 提取年级
if 4 >= len(input_grade) >= 2:# 存在
info = Student.query.filter(Student.Grade == input_grade).all()
if not info:
input_grade = "%" + input_grade + "%"
info = Student.query.filter(Student.Grade.like(input_grade)).all()
if not info:
info = []
return info
def to_Data():
# data = request.get_data() # 获取前端数据
# data = str(data, 'utf-8') # 转utf-8
# data = json.loads(data) # json转字典
data = json.loads(request.get_data().decode("utf-8"))
if data:
return data
else:
return {}
def to_Json(list = None):
if list:
data = json.dumps(list, ensure_ascii = False)
else:
data = "0"
return data
def to_List(info, page): # page为页数
list = []
limit = 10 # 限制返回数据条数
index = len(info) # 行索引
for row in range(index):
dic_stu = {
'sno': info[row].SNo,
'image_url':info[row].Avatar,
'name': info[row].SName,
'grade': info[row].Grade,
'group': info[row].Group,
'contact':{
'phone': info[row].Telephone,
'wx': info[row].WeChat,
'qq': info[row].QQ,
'email': info[row].MailBox,
'other': info[row].Other
},
'graduation':{
'job': info[row].Occupation,
'address': info[row].WorkAddress,
'study': info[row].Direction
},
}
list_pro = []
pro_info = Project.query.filter(Project.SNo == info[row].SNo).all()
for row_ in range(len(pro_info)):
dic_pro = {
'ID':pro_info[row_].ID,
'name': pro_info[row_].Project,
'prize': pro_info[row_].Award,
'code': pro_info[row_].Code
}
list_pro.append(dic_pro)
dic_stu['project_arr'] = list_pro
list.append(dic_stu) # 合并
total = limit * page
list = list[total-limit:total] # 索引,位置
return list
def new_avatar_name(avatar_name):
now_time = datetime.datetime.now().strftime("%Y%m%d%H%M%S")
rand_num = random.randint(10,99) # 随机10到99
name = secure_filename(avatar_name)
ext = name.rsplit('.', 1)[1] # 扩展名
avatar_name = str(now_time) + str(rand_num) + '.' + ext # 合成
return avatar_name
def create_xlsx(info):
workbook = xlwt.Workbook(encoding = 'utf-8')
worksheet = workbook.add_sheet('新思路成员信息一览表', cell_overwrite_ok = True)
alignment = xlwt.Alignment() # 对齐格式
alignment.horz = xlwt.Alignment.HORZ_CENTER # 水平居中
alignment.vert = xlwt.Alignment.VERT_CENTER #
font = xlwt.Font() # 字体
font.bold = True # 设置黑体
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
pattern.pattern_fore_colour = 27 # 浅色
borders = xlwt.Borders()
borders.left = xlwt.Borders.THIN # THIN:实线 NO_LINE:无 DASHED:虚线
borders.right = xlwt.Borders.THIN
borders.top = xlwt.Borders.THIN
borders.bottom = xlwt.Borders.THIN
borders_ = xlwt.Borders()
borders_.bottom = xlwt.Borders.THIN
tall = xlwt.easyxf('font:height 700;')
worksheet.row(0).set_style(tall)
tall = xlwt.easyxf('font:height 360;')
worksheet.row(1).set_style(tall)
tall = xlwt.easyxf('font:height 360;')
worksheet.row(2).set_style(tall)
worksheet.col(0).width = 256*13 # 学号
worksheet.col(4).width = 256*12 # 电话
worksheet.col(5).width = 256*12 # 微信
worksheet.col(6).width = 256*12 # QQ
worksheet.col(7).width = 256*18 # 邮箱
worksheet.col(10).width = 256*15 # 地址
worksheet.col(11).width = 256*27 # 方向
worksheet.col(13).width = 256*25
worksheet.col(14).width = 256*25
worksheet.col(15).width = 256*25
worksheet.col(16).width = 256*25
worksheet.col(17).width = 256*25
style0 = xlwt.XFStyle()
style0.alignment = alignment
style0.font = font
style0.pattern = pattern
style0.borders = borders
worksheet.write_merge(0, 0, 0, 17, 'New-Thread成员信息一览表', style0)
style1 = xlwt.XFStyle()
style1.alignment = alignment
style1.font = font
style1.borders = borders
worksheet.write_merge(1, 1, 0, 3, '个人信息', style1)
worksheet.write_merge(1, 1, 4, 8, '联系方式', style1)
worksheet.write_merge(1, 1, 9, 11, '毕业去向(工作/研究生/留学生)', style1)
worksheet.write_merge(1, 1, 12, 17, '参与项目', style1)
style2 = xlwt.XFStyle()
style2.alignment = alignment
style2.borders = borders
a = ['学号','姓名','年级','组别','电话','微信','QQ','邮箱','其它','职业','地址(工作单位)','研究方向(岗位/研究生技术方向)','-','项目1','项目2','项目3','项目4','项目5']
for i in range(18):
worksheet.write(2, i, a[i], style2)
style3 = xlwt.XFStyle()
style3.alignment = alignment
style3.borders = borders
if info:
i = 3 # 控制行
pi = 3
for row in range(len(info)):
stu_info = [info[row].SNo, info[row].SName, info[row].Grade, info[row].Group, info[row].Telephone, info[row].WeChat, info[row].QQ,
info[row].MailBox, info[row].Other, info[row].Occupation, info[row].WorkAddress, info[row].Direction]
j = 0 # 控制信息列
pj = 13 # 工程列
for content in stu_info:
worksheet.write_merge(i, i+2, j, j, content, style3) # 合并单元格参数(从0开始): 1-3行,0-0列,内容,格式
j = j+1
if j == 12:
break
style4 = xlwt.XFStyle()
style4.borders = borders_
worksheet.write(i, 12, '项目名称')
worksheet.write(i+1, 12, '获奖情况')
worksheet.write(i+2, 12, '源码', style4)
project = Project.query.filter(Project.SNo == info[row].SNo).all()
for row in range(len(project)):
pro_info = [project[row].Project, project[row].Award, project[row].Code]
for content in pro_info:
worksheet.write(pi, pj, content, style3)
pi = pi+1 # 加行
pj = pj + 1 # 加列
pi = pi - 3 # 还是一个学生,所以回到这一次的初始行
i = i + 3 # 隔行输出
pi = pi + 3 # 下一初始行
basedir = os.path.dirname(__file__) # 运行路径
excel_path = os.path.join(basedir, 'static', '成员信息一览表.xls') # 重命名后合成文件在服务器的路径
excel_path = excel_path.replace('\\', '/') # 若不换成/ Linux服务器会报错 位置:static/*.xls
workbook.save(excel_path) # 写入
return excel_path
return ("0")
数据库配置信息(config.py)
DIALECT ='mysql'
DRIVER = 'mysqldb'
USERNAME = 'root'
PASSWORD = 'password' # 此处填写你的数据库密码
HOST = 'localhost' # 部署到服务器不能用127.0.0.1 得用localhost
PORT = '3306'
DATABSE = 'db_info' # 此处为你建的数据库的名称
SQLALCHEMY_DATABASE_URI ="{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USERNAME,PASSWORD,HOST,PORT,DATABSE)
SQLALCHEMY_TRACK_MODIFICATIONS = False
创建相应数据库模型(models.py)
from exts import db
class Admin(db.Model):
__tablename__ = 'admin'
Adminaccount = db.Column(db.String(255, 'utf8_general_ci'), primary_key=True)
Password = db.Column(db.String(255, 'utf8_general_ci'), nullable=False)
class Project(db.Model):
__tablename__ = 'project'
ID = db.Column(db.Integer, primary_key=True)
SNo = db.Column(db.ForeignKey('student.SNo', ondelete='CASCADE', onupdate='CASCADE'), nullable=False, index=True)
Project = db.Column(db.String(255))
Award = db.Column(db.String(255))
Code = db.Column(db.String(255))
student = db.relationship('Student', primaryjoin='Project.SNo == Student.SNo', backref='projects')
class Student(db.Model):
__tablename__ = 'student'
SNo = db.Column(db.String(255, 'utf8_general_ci'), primary_key=True, index=True)
Avatar = db.Column(db.String(255, 'utf8_general_ci'), index=True)
SName = db.Column(db.String(255, 'utf8_general_ci'), nullable=False)
Grade = db.Column(db.String(255, 'utf8_general_ci'), nullable=False)
Group = db.Column(db.String(255, 'utf8_general_ci'), nullable=False)
Telephone = db.Column(db.String(255, 'utf8_general_ci'))
WeChat = db.Column(db.String(255, 'utf8_general_ci'))
QQ = db.Column(db.String(255, 'utf8_general_ci'))
MailBox = db.Column(db.String(255, 'utf8_general_ci'))
Other = db.Column(db.String(255, 'utf8_general_ci'))
Occupation = db.Column(db.String(255, 'utf8_general_ci'))
WorkAddress = db.Column(db.String(255, 'utf8_general_ci'))
Direction = db.Column(db.String(255, 'utf8_general_ci'))
将models中所写模型映射到数据库中(manager.py)
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app
from exts import db
manager = Manager(app)
migrate = Migrate(app,db) # 使用Migrate绑定app和db
manager.add_command('db',MigrateCommand) #添加迁移脚本的命令到manager中
if __name__ == '__main__':
manager.run()
- 映射
打开命令提示符,切换到项目文件目录
cd /d D:\Flask\成员信息管理系统
- 执行以下命令
python manager.py db init
python manager.py db migrate
python manager.py db upgrade