Flask 蓝图基本建立
安装配置
flask_script
pip install flask_script
flask_migrate
pip install flask_migrate
flask_wtf
pip install flask_wtf
源码链接:https://pan.baidu.com/s/1Btb8764qr2DBpJNBxV0XJQ
提取码:rhjl
目录
步骤
布置配置环境
config.py
# 配置文件
import os
# 配置文件
class Config:
# 获取文件路径
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# 配置数据库sqlite
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'sqlite3.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
# session秘钥
SECRET_KEY='78325EFWEGWEGWECAQ'
oasys/user/__ init__ .py
from flask import Blueprint
# 创建蓝图
ubp=Blueprint('ubp',__name__)
oasys/__ init __.py
from flask import Flask
# 数据库
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
# 获取数据库
db=SQLAlchemy()
migrate=Migrate()
def createApp(config):
app=Flask(__name__)
app.config.from_object(config)
# 数据库初始化
db.init_app(app)
migrate.init_app(app,db)
# 蓝图配置文件
from oasys.user.views import ubp
# 注册蓝图
app.register_blueprint(ubp)
return app
类模型
oasys/user/models.py
#存放类模块
import datetime
from oasys import db
#抽象父类
class Base(db.Model):
__abstract__=True
id = db.Column(db.INT, primary_key=True, autoincrement=True)
#添加员工
def save(self):
# 保存对象
db.session.add(self)
# 提交事务
db.session.commit()
def update(self):
db.session.commit()
def delete(self):
# 删除对象
db.session.delete(self)
# 提交事务
db.session.commit()
#职位
class Position(Base):
__tablename__="position"
name=db.Column(db.String(32)) #职位名称
level=db.Column(db.Integer) #级别
#关系属性
#为了查询方便,flask提供了关系属性,为了方便查询,但是不会在数据库中生成相应的字段
persons=db.relationship("Person",backref='position')
department_id=db.Column(db.Integer,db.ForeignKey("department.id"))
#当知道职位查询所有的员工时,通过 职位对象.persons就可以获得所有的员工
# 当员工查询对应的职位的时候,通过 员工对象.position就可获得对应的职位
# 职员
class Person(Base):
"""雇员表"""
__tablename__ = "person"
username = db.Column(db.VARCHAR(100))
password = db.Column(db.VARCHAR(64))
nickname = db.Column(db.String(64), nullable=True) # 昵称
gender = db.Column(db.String(8), nullable=True) # 性别
age = db.Column(db.Integer, nullable=True) # 年龄
workid = db.Column(db.String(32), nullable=True) # 工号
phone = db.Column(db.String(64), nullable=True) # 电话
email = db.Column(db.String(64), nullable=True) # 邮箱
photo = db.Column(db.String(64), nullable=True) # 照片
address = db.Column(db.Text, nullable=True) # 地址
score = db.Column(db.Float, nullable=True) # 绩效
#关系属性
#职位和员工一对多关系
position_id=db.Column(db.Integer,db.ForeignKey("position.id"))
# 考勤关系属性
attendances = db.relationship('Attendance', backref='person')
#职位与权限中间表
permission_position=db.Table(
'permission_position',
db.Column("id",db.Integer,primary_key=True,autoincrement=True),
db.Column("position_id",db.Integer,db.ForeignKey("position.id")), #关联position
db.Column("permission_id",db.Integer,db.ForeignKey("permission.id")), #关联permission
)
#权限表
class Permission(Base):
__tablename__="permission"
name=db.Column(db.String(32)) #权限名称
desc=db.Column(db.String(128)) #权限描述
#关系属性
positions=db.relationship(
'Position',# 和模型类进行关联
backref='permissions',
secondary=permission_position
)
#部门表
class Department(Base):
__tablename__='department'
#实体属性
name=db.Column(db.String(32))
description=db.Column(db.String(128))
#关系属性
positions=db.relationship('Position',backref='dept')
# 考勤模型类
class Attendance(Base):
__tablename__ = 'attendance'
# 实体属性
reason = db.Column(db.Text) # 考勤原因
atype = db.Column(db.String(32)) # 考勤类型
adate = db.Column(db.Float) # 请假天数
start_time = db.Column(db.Date) # 开始时间
end_time = db.Column(db.Date) # 结束时间
examine = db.Column(db.String(32), nullable=True, default='审核中') # 检察官
astatus = db.Column(db.String(32), default='申请中') # 状态...
# 关系属性
person_id = db.Column(db.Integer, db.ForeignKey('person.id'))
# 新闻模板类
class News(Base):
__tablename__="news"
# 实体属性
title=db.Column(db.String(32)) #标题
author=db.Column(db.String(32)) #作者
nav=db.Column(db.Text) #内容
photo=db.Column(db.String(32)) #图片
Time=db.Column(db.DateTime) #时间
视图类
oasys/user/views.py
import hashlib
from oasys.user import ubp
from oasys.user.models import Person, db, Position, Permission, Department,Attendance,News
from flask import render_template, redirect,request
import os, time,datetime
from functools import wraps
# 登录装饰器
def Login_Decorator(func):
@wraps(func)
def inner():
person_name = request.cookies.get('person_name')
if person_name:
return func()
else:
return redirect('login')
return inner
# 首页
@ubp.route('/')
@Login_Decorator
def index():
person_id = request.cookies.get("person_id")
news_list=News.query.all()
attendance_me_list = Attendance.query.filter(Attendance.person_id == person_id).all()
return render_template('index.html',**locals())
#登录
@ubp.route('/login', methods=['GET', 'POST'])
def login():
msg = ''
print("asd")
if request.method == 'POST':
# 1.获取用户名和密码
username = request.form.get('username')
password=hashlib.md5(request.form.get("password").encode()).hexdigest()
# 2.查询数据库 (用户名和密码)
person_obj = Person.query.filter(Person.username == username, Person.password == password).first()
# 3.判断
if person_obj:
# (1).正确 --->> 重定向到首页
response = redirect('/')
# 4.将用户名保存到cookie中,用于首页显示
response.set_cookie('person_name', person_obj.nickname)
response.set_cookie('person_id', str(person_obj.id))
return response
# (2).错误--->> 提示错误信息
msg = '用户名或者密码错误'
# get方式或者用户名校验失败后返回登录页面
return render_template('login.html', msg=msg)
#登录退出
@ubp.route('/logout')
@Login_Decorator
def logout():
response = redirect('/login')
# 1.清除所有的cookie
response.delete_cookie('person_name')
# 2.重定向到登录界面
return response
# 职员管理
@ubp.route('/person')
@Login_Decorator
def person():
res=request.args.get("filter")
print(res)
search=request.args.get("search")
department_list = Department.query.all()
flag = False
if res=="all" or res==None:
Filter=0
person_list = Person.query.all()
else:
flag=True
Filter=int(res)
pos_list=Position.query.filter(Position.department_id==Filter).all()
person_list=[ps for person in pos_list for ps in person.persons] #遍历所有部门的成员存入字典
if search!=None:
if flag:
person_list=[person for person in person_list if search in person.nickname]
else:
person_list=Person.query.filter(Person.nickname.like("%"+search+"%")).all()
return render_template("person.html",**locals())
# 添加员工
@ubp.route('/add_person',methods=["GET","POST"])
def add_person():
if request.method=="GET":
position_list=Position.query.all()
return render_template("add_person.html",position_list=position_list)
else:
username=request.form.get("username")
password=hashlib.md5(request.form.get("password").encode()).hexdigest() #md5进行加密
position_id=request.form.get("position_id")
user=Person(username=username,password=password,position_id=position_id)
user.save()
return redirect("/person")
# 删除员工
@ubp.route('/del_person')
@Login_Decorator
def del_person():
id=request.args.get('id')
person=Person.query.get(id)
person.delete()
return redirect("/person")
# 编辑员工
@ubp.route('/update_person',methods=["GET","POST"])
@Login_Decorator
def update_person():
id = request.args.get('id')
person = Person.query.get(id)
if request.method=="GET":
position_list = Position.query.all()
return render_template("edit_person.html",**locals())
else:
username=request.form.get("username")
password=hashlib.md5(request.form.get("password").encode()).hexdigest() #md5进行加密
nickname=request.form.get("nickname")
gender=request.form.get("gender")
age=request.form.get("age")
phone=request.form.get("phone")
email=request.form.get("email")
adress=request.form.get("address")
position_id=request.form.get("position_id")
#文件保存
photo=request.files.get("photo")
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
Time=int(time.time())
if len(photo.filename)!=0:
#替换成新图片时删除以前图片,并判断是否是第一次添加
photo_name="static/img/"+str(Time)+photo.filename
if person.photo.startswith("/static/"):
os.remove(BASE_DIR+person.photo)
path=os.path.join(BASE_DIR,photo_name)
photo.save(path)
else:
photo_name = person.photo
person.username=username
person.password=password
person.nickname=nickname
person.gender=gender
person.age=age
person.phone=phone
person.email=email
person.adress=adress
person.photo=photo_name
person.position_id=position_id
person.update()
return redirect("/person")
#员工详情
@ubp.route('/detail_person')
@Login_Decorator
def detail_person():
id = request.args.get('id')
person = Person.query.get(id)
return render_template("detail_person.html", person=person)
#部门管理
@ubp.route('/department')
@Login_Decorator
def department():
department_list=Department.query.all()
return render_template("department.html",department_list=department_list)
#部门编辑
@ubp.route('/edit_department',methods=["GET","POST"])
@Login_Decorator
def edit_department():
if request.method=="POST":
id=request.form.get("id")
department = Department.query.get(id)
name=request.form.get("name")
description=request.form.get("description")
department.name=name
department.description=description
department.update()
return redirect("/department")
else:
id = request.args.get("id")
department = Department.query.get(id)
return render_template("edit_department.html",department=department)
# 部门删除
@ubp.route('/del_department')
@Login_Decorator
def del_department():
id = request.args.get("id")
department = Department.query.get(id)
# 删除该部门所有职位及其所有职员
for pos in department.positions:
for person in pos.persons:
person.delete()
pos.delete()
department.delete()
return redirect("/department")
# 查看职位
@ubp.route('/position')
@Login_Decorator
def position_read():
id = request.args.get("id")
department = Department.query.get(id)
position_list=department.positions
return render_template("position.html",position_list=position_list,dept=department)
# 添加部门
@ubp.route('/add_department',methods=["GET","POST"])
@Login_Decorator
def add_department():
if request.method=="POST":
name=request.form.get("name")
description=request.form.get("description")
department=Department(name=name,description=description)
department.save()
return redirect("/department")
return render_template("add_department.html")
#职位删除
@ubp.route('/del_position')
@Login_Decorator
def del_position():
id = request.args.get("id")
dept_id = request.args.get("dept_id")
position = Position.query.get(id)
for person in position.persons:
person.delete()
position.delete()
return redirect("/position?id="+dept_id)
#职位编辑
@ubp.route('/edit_position',methods=["POST"])
@Login_Decorator
def edit_position():
pass
# 职位添加
@ubp.route('/add_position',methods=["POST"])
@Login_Decorator
def add_position():
name=request.form.get("name")
level=request.form.get("level")
department_id=request.form.get("dept_id")
pos=Position(name=name,level=level,department_id=department_id)
pos.save()
return redirect("/position?id="+department_id)
# 个人考勤管理页面
@ubp.route('/attendance_me')
@Login_Decorator
def attendance_me():
person_id = request.cookies.get("person_id")
attendance_me_list=Attendance.query.filter(Attendance.person_id==person_id).all()
return render_template("attendance_me.html",attendance_me_list=attendance_me_list)
# 考勤申请
@ubp.route('/add_ks_person',methods=["GET","POST"])
@Login_Decorator
def add_ks_person():
reason=request.form.get("reason")
a_type=request.form.get("type")
Day=request.form.get("day")
start_time=datetime.datetime.strptime(request.form.get("start"), "%Y-%m-%d")
end_time=datetime.datetime.strptime(request.form.get("end"), "%Y-%m-%d")
person_id=request.cookies.get("person_id")
attendance=Attendance(reason=reason,atype=a_type,adate=Day,start_time=start_time,end_time=end_time,person_id=person_id)
attendance.save()
return redirect("/attendance_me")
# 下属考勤管理
@ubp.route('/attendance_subordinate')
@Login_Decorator
def attendance_subordinate():
# 获取下属考勤情况
"""
步骤:
1.获取职员信息
2.获取职员的职务等级
3.获取职员所在部门中低于该职员等级的职务
4.获取低于等级的职务的所有职员
5.再获取其所有考勤情况
"""
id=request.args.get("id")
flag=request.args.get("flag")
print(flag)
examine_id=request.cookies.get("person_id")
if id==None:
person_id=request.cookies.get("person_id")
# 1.获取职员信息
person=Person.query.get(person_id)
# 2.获取职员的职务等级
pos=Position.query.filter(Position.id==person.position_id).first()
level=pos.level
# 3. 获取职员所在部门中低于该职员等级的职务
department=Department.query.filter(Department.id==pos.department_id).first()
low_poses=[low_pos for low_pos in department.positions if low_pos.level<level]
# 4.获取低于等级的职务的所有职员
low_persons=[low_pos.persons for low_pos in low_poses]
# 5.再获取其所有考勤情况
attendance_list=[attendance_me for low_person in low_persons for person in low_person for attendance_me in person.attendances]
return render_template("attendance_subordinate.html",attendance_list=attendance_list)
else:
attendance_me=Attendance.query.get(id)
if flag:
attendance_me.astatus="通过"
else:
attendance_me.astatus = "驳回"
examine=Person.query.get(examine_id).nickname
attendance_me.examine=examine
attendance_me.update()
return redirect("/attendance_subordinate")
# 新闻页面
@ubp.route('/News')
@Login_Decorator
def NEWS():
news_list=News.query.all()
return render_template("news.html",news_list=news_list)
# 添加新闻
@ubp.route('/add_news',methods=["GET","POST"])
@Login_Decorator
def add_news():
if request.method=="POST":
title=request.form.get("title")
author=request.form.get("author")
content=request.form.get("content")
# 文件保存
photo = request.files.get("picture")
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
Time = int(time.time())
photo_name = "static/img/news/" + str(Time) + photo.filename
path = os.path.join(BASE_DIR, photo_name)
photo.save(path)
news=News(title=title,author=author,nav=content,photo=photo_name,Time=datetime.datetime.now().replace(microsecond=0))
news.save()
return redirect("/News")
return render_template("add_news.html")
# 新闻详情
@ubp.route('/detail_news')
@Login_Decorator
def detail_news():
id=request.args.get("id")
news=News.query.get(id)
return render_template("detail_news.html",news=news)
# 新闻编辑
@ubp.route('/edit_news',methods=["GET","POST"])
@Login_Decorator
def edit_news():
if request.method=="POST":
id=request.form.get("id")
news=News.query.get(id)
title=request.form.get("title")
author=request.form.get("author")
nav=request.form.get("content")
# 文件保存
photo = request.files.get("picture")
BASE_DIR = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
Time = int(time.time())
if len(photo.filename) != 0:
# 替换成新图片时删除以前图片,并判断是否是第一次添加
photo_name = "static/img/news/" + str(Time) + photo.filename
if news.photo.startswith("/static/"):
os.remove(BASE_DIR + news.photo)
path = os.path.join(BASE_DIR, photo_name)
photo.save(path)
else:
photo_name = news.photo
news.title=title
news.author=author
news.nav=nav
news.photo=photo_name
news.Time=datetime.datetime.now().replace(microsecond=0)
news.update()
return redirect("/News")
news = News.query.get(request.args.get("id"))
return render_template("edit_news.html",news=news)
# 新闻删除
@ubp.route('/del_news')
@Login_Decorator
def del_news():
id=request.args.get("id")
news=News.query.get(id)
news.delete()
return redirect("/News")
# 权限管理页面
@ubp.route('/permission')
@Login_Decorator
def permission():
per_list=Permission.query.all()
return render_template("permission.html",per_list=per_list)
# 权限添加界面
@ubp.route('/add_permission',methods=["GET","POST"])
@Login_Decorator
def add_permission():
if request.method=="POST":
name=request.form.get("name")
description=request.form.get("description")
per=Permission(name=name,desc=description)
per.save()
return redirect("/permission")
return render_template("add_permission.html")
# 权限编辑界面
@ubp.route('/edit_permission',methods=["GET","POST"])
@Login_Decorator
def edit_permission():
if request.method=="POST":
id=request.form.get("id")
name = request.form.get("name")
description = request.form.get("description")
per=Permission.query.get(id)
per.name=name
per.desc=description
per.update()
return redirect("/permission")
per=Permission.query.get(request.args.get("id"))
return render_template("edit_permission.html",per=per)
# 权限删除
@ubp.route('/del_permission')
@Login_Decorator
def del_permission():
pass
# 关联部门
@ubp.route('/position_permission',methods=["GET","POST"])
@Login_Decorator
def position_permission():
if request.method=="POST":
per_id=request.form.get("id")
position_ids=request.form.getlist("position_ids")
permission=Permission.query.get(per_id)
# 为部门添加权限
for position_id in position_ids:
pos=Position.query.get(position_id)
pos.permissions.append(permission)
pos.update()
return redirect("/position_permission?id="+per_id)
else:
# 展示权限页面
id=request.args.get("id")
pos_list=Position.query.all()
per=Permission.query.get(id)
per_pos_list=[poss.name for poss in per.positions]
return render_template("position_permission.html",pos_list=pos_list,per_pos_list=per_pos_list,per=per)
文件运行
manage.py
# 项目启动
from flask_migrate import MigrateCommand
from flask_script import Manager, Command
from config import Config
from oasys import createApp
app=createApp(Config)
# 项目管理
manager=Manager(app)
# 项目启动类
class Run(Command):
def run(self):
app.run(debug=True,port=2020)
# 添加
manager.add_command("run",Run)
# 添加数据库
manager.add_command('db',MigrateCommand)
# 初始化数据库命令
# python manage.py db init
# 数据库同步命令
# python manage.py db migrate
# python manage.py db upgrade
if __name__ == '__main__':
manager.run()
初始化数据库
# 初始化数据库命令
# python manage.py db init
# 数据库同步命令
# python manage.py db migrate
# python manage.py db upgrade
数据库数据
考勤
INSERT INTO "attendance"("id", "reason", "atype", "adate", "start_time", "end_time", "examine", "astatus", "person_id") VALUES (1, '有事', '事假', 3.0, '2020-05-04', '2020-05-07', '审核中', '申请中', 1);
INSERT INTO "attendance"("id", "reason", "atype", "adate", "start_time", "end_time", "examine", "astatus", "person_id") VALUES (2, '有事', '事假', 3.0, '2020-05-12', '2020-05-15', '张三', '通过', 4);
部门类
INSERT INTO "department"("id", "name", "description") VALUES (1, '市场部', '负责市场相关');
INSERT INTO "department"("id", "name", "description") VALUES (2, '技术部', '负责技术相关');
INSERT INTO "department"("id", "name", "description") VALUES (3, '财务部', '负责财务相关');
INSERT INTO "department"("id", "name", "description") VALUES (4, '新媒体部', '负责新媒体相关');
INSERT INTO "department"("id", "name", "description") VALUES (5, '人事部', '负责人事相关');
INSERT INTO "department"("id", "name", "description") VALUES (6, '董事会', '董事会');
新闻类
INSERT INTO "news"("id", "title", "author", "nav", "photo", "Time") VALUES (1, '123', '123', ' 321
', 'static/img/news/1597470100315899.jpg', '2020-08-15 13:46:36.000000');
权限表类
INSERT INTO "permission"("id", "name", "desc") VALUES (1, '新闻管理', '对新闻进行增删改查');
INSERT INTO "permission"("id", "name", "desc") VALUES (2, '人事管理', '对人事进行增删改查');
INSERT INTO "permission"("id", "name", "desc") VALUES (3, '考勤管理', '对考勤进行增删改查');
INSERT INTO "permission"("id", "name", "desc") VALUES (4, '权限管理', '对权限进行增删改查');
INSERT INTO "permission"("id", "name", "desc") VALUES (5, '董事会', '董事会很好');
职员类
INSERT INTO "person"("id", "username", "password", "nickname", "gender", "age", "workid", "phone", "email", "photo", "address", "score", "position_id") VALUES (1, 'zhangsan', '01d7f40760960e7bd9443513f22ab9af', '张三', '男', 18, 'zs123', '123', '123@qq.com', 'static/img/1597406889315899.jpg', '广州', 16.5, 1);
INSERT INTO "person"("id", "username", "password", "nickname", "gender", "age", "workid", "phone", "email", "photo", "address", "score", "position_id") VALUES (3, 'wangwu', 'wangwu', '王五', '女', 21, 'ww123', '321', '321@qq.com', '3.jpg', '北京', 20.0, 3);
INSERT INTO "person"("id", "username", "password", "nickname", "gender", "age", "workid", "phone", "email", "photo", "address", "score", "position_id") VALUES (4, 'zhaoliu', '01d7f40760960e7bd9443513f22ab9af', '赵六', '男', 19, 'zl123', '311', '123@qq.com', '4.jpg', '南京', 12.5, 12);
职位
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (1, '市场部_部长', 2, 1);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (3, '人事部_部长', 2, 5);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (4, '人事部_主任', 3, 5);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (5, '技术部_部长', 2, 2);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (6, '技术部_主任', 3, 2);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (7, '新媒体部_部长', 2, 4);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (8, '新媒体部_主任', 3, 4);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (9, '财务部_部长', 2, 3);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (10, '财务部_主任', 3, 3);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (11, '市场部_主任', 3, 1);
INSERT INTO "position"("id", "name", "level", "department_id") VALUES (12, '市场部_职员', 1, 1);
职位与权限中间表
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (1, 1, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (2, 11, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (3, 12, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (4, 3, 2);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (5, 4, 2);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (6, 3, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (7, 4, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (8, 5, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (9, 6, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (10, 7, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (11, 8, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (12, 9, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (13, 10, 1);
INSERT INTO "permission_position"("id", "position_id", "permission_id") VALUES (14, 5, 2);