用Python的Flask框架写微信小程序及其管理网页后台(实现篇)

文章目录

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

代码实现篇

创建数据库

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

代码框架

用Python的Flask框架写微信小程序及其管理网页后台(实现篇)_第1张图片

主程序(app.py)

  • 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)

  • exts.py

    from flask_sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    

主程序用到的方法(methods.py)

  • 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)

  • 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)

  • 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)

  • 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

上一篇(准备篇):https://blog.csdn.net/qq_42766994/article/details/89401754
下一篇(测试篇):https://blog.csdn.net/qq_42766994/article/details/89437977

你可能感兴趣的:(Python-Flask)