文章目录

  • 代码实现篇
  • 创建数据库
  • 代码框架
  • 主程序(app.py)
  • 扩展(exts.py)
  • 主程序用到的方法(methods.py)
  • 数据库配置信息(config.py)
  • 创建相应数据库模型(models.py)
  • 将models中所写模型映射到数据库中(manager.py)


代码实现篇

创建数据库

  • 利用命令提示符登录数据库(方法在准备篇,这里不做阐述)
  • 创建一个名为db_info的数据库(SQL语句)
create database db_info charset utf8;

代码框架

python可以写小程序代码吗 python能写微信小程序吗_python可以写小程序代码吗

主程序(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