在前一段时间,领导提出了一个需求,部门有大量工作台账都是纸质的,但这些材料越积越多,使用效率却很低。要找份材料经常要吧啦吧啦找个半天,还容易丢失,就希望能够找个电子化的东西来存放台账。
做资料的电子化方案还挺多,但麻烦的是什么样的软件符合我们的需求。一开始我想的是BI软件,不过对于部门来讲BI软件的成本实在是太高,而且我要处理的台账,有很多文字性的记录,BI更多还是偏向于可量化的数据;某书云文档也有同样的问题,他们对于文字资料的展示不够理想。
找来找去,最后决定还是自己写个web应用比较实在。老板的需求其实很简单,但我们在执行的时候还是要具体问题具体分析。第一,公司、部门的规模还在扩大,工作制度也在完善,资料量一直在快速增长,因此要准备好数据库来存数据;而且还要考虑到老板一开始只是用一部分资料来试试水,做的好必然要引入更多数据。第二,前端页面要在尽可能简单的情况下展现数据,我们毕竟是个人开发,做得太复杂没必要。
最后,因为我之前学的是python,所以选择的是用flask框架做前后端交互。flask是一个灵活、易上手的web框架。
flask不像django那样,在建立项目时就自动提供好项目的结构,而是根据需要自由搭建,例如在一些简单的项目中,完全可以把服务器代码都写在app.py
,就像我之前做的echars示那样。
不过,这次项目体量较大,因此我们还是要把不同的配置文件分离开来,网上能找到的写法有很多种,这里我因为是个人开发,只做最核心的功能。
在这里面,app.py
用来初始化项目,与之相关的配置、数据库映射、蓝图我们放到其他文件里进行引入。我们先引入Flask,app = Flask(__name__)
创建项目;app.secret_key='QWERTYUIOP
用于数据加密,提高数据安全性;app.config.from_object(Config)
从config中导入配置信息,应用到flask项目;db.__init__(app)
导入数据库映射,对数据库进行初始化;from blueprints.login import bp as login_bp
用于导入蓝图,app.register_blueprint(login_bp)
对蓝图进行注册。
python
from flask import Flask, render_template
from config import Config
from models import db
# from models import person_data
app = Flask(__name__)
app.secret_key='QWERTYUIOP'#对信息加密
# 引入数据库的登陆配置
app.config.from_object(Config)
# 把数据库初始化,导入登陆信息
db.__init__(app)
# 导入蓝图
from blueprints.login import bp as login_bp
app.register_blueprint(login_bp)
@app.route("/index.html")
def hello_world():
return render_template("/index.html")
if __name__ == "__main__":
app.run(debug="true")
Config
- Config:是自定义的配置类,用于配置应用程序的一些参数。
在该项目中,我们还会在项目文件夹创建一个config.py用来放置配置信息,这里我存放了mysql数据库的登陆信息。
python
class Config:
HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = ""
PASSWORD = ""
DATABASE = "bisystem"
DB_URI = f"mysql+pymysql://{ USERNAME }:{ PASSWORD }@{ HOSTNAME }:{ PORT }/{ DATABASE }?charset=utf8mb4"
SQLALCHEMY_DATABASE_URI = DB_URI
HOSTNAME填写服务器的IP地址,如果mysql数据库部署在当前机器上,就用 "127.0.0.1",数据库已经部署到了服务器上,就用服务器的公网IP。
而在app.py 中,用from config import Config来引入这个Config配置。
models
models中存放的是对数据库的映射,这里我用SQLAlchemy来操作数据库,他是Python中有名的ORM工具,通过python语法来操作数据库而不用我们编写sql语句。在 models,要通过定义类,映射数据库中表的信息。from flask_sqlalchemy import SQLAlchemy
引入SQLAlchemy。 db = SQLAlchemy()
的作用是创建一个 SQLAlchemy 对象实例。
针对users表我们创建一个users类,db.Model表示模型类继承自 db.Model
基类,从而获取了 SQLAlchemy 提供的各种功能和方法来操作数据库。id、 user、pwd 、 position对应数据库中的表头及其数据类型。最后,to_dict以字典的形式返回数据。
python
class users(db.Model):
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.String(100))
pwd = db.Column(db.String(100))
position = db.Column(db.String(20))
def to_dict(self):
return {
"id":self.id,
"user":self.user,
"pwd":self.pwd,
"position":self.position
}
在app.py 通过from models import db
导入数据库模型。
blueprint
蓝图的基本概念是:在蓝图被注册到应用之后,所要执行的操作的集合。当分配 请求时, Flask 会把蓝图和视图函数关联起来,并生成两个端点之前的 URL 。
蓝图用来存放与路由相关的操作,在制作复杂项目的过程中,我们可以根据功能的不同,在蓝图中存放路由操作,让我们的项目更加清晰。
下面这个蓝图用来处理登录相关的处理:
python
from flask import Blueprint, render_template, json,request, session, redirect
from models import users
bp = Blueprint("login", __name__, url_prefix="/")
# 登陆判断
@bp.route('/login.html', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template("login.html")
user = request.form.get("user")
pwd = request.form.get("pwd")
have_user = users.query.filter_by(user=user,pwd=pwd).first()
if have_user:
# 登录信息
session["user_info"] = {
'user_id' :have_user.id,
"name": user,
'position' :have_user.position
}
return redirect('/index.html')
else:
return render_template('login.html', msg='用户名或密码输入错误')
# 登录信息检测
@bp.route('/index.html')
def index():
user_info = session.get('user_info')
if not user_info:
return redirect('/login.html')
return render_template('/index.html', user_info=user_info)
# 登出
@bp.route('/logout')
def logout():
session.clear()
return redirect('/login.html')
from models import users
引入users表,这张表储存了用户的登陆信息。
bp = Blueprint("login", __name__, url_prefix="/")
的作用是在 Flask 应用程序中创建一个蓝图对象。第一个参数login 是蓝图的名称,这个通常根据蓝图要实现的功能命名;第二个参数蓝图所在模块的名称,通常使用 __name__
变量作为参数;第三个参数是可选项,用于指定蓝图中所有路由的 URL 前缀。
python
# 登陆判断
@bp.route('/login.html', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template("login.html")
user = request.form.get("user")
pwd = request.form.get("pwd")
have_user = users.query.filter_by(user=user,pwd=pwd).first()
if have_user:
# 登录信息
session["user_info"] = {
'user_id' :have_user.id,
"name": user,
'position' :have_user.position
}
users.query.filter_by(user=user,pwd=pwd).first()
else:
return render_template('login.html', msg='用户名或密码输入错误')
html
<form method="post">
<div class="container" action="/login">
<div class="tit">欢迎登录人员信息BI</div>
<input type="text" name="user" placeholder="账号">
<input type="password" name="pwd" placeholder="密码">
<input type="submit" name="登录">
</div>
</form>
这个方法用来匹配用户的登录信息。在页面发送请求的时候,我们用POST方法发送用户名和密码比较安全,通过request.form.get 用来取得用户在登录页面输入的信息。users.query.filter_by(user=user,pwd=pwd).first()
把用户信息与数据库信息进行比对,如果验证通过就重定向到主页 users.query.filter_by(user=user,pwd=pwd).first()
否则就返回登录页面并返回错误信息。
python
# 登录信息检测
@bp.route('/index.html')
def index():
user_info = session.get('user_info')
if not user_info:
return redirect('/login.html')
return render_template('/index.html', user_info=user_info)
session
是 Flask 框架中的一个对象,用于在不同请求之间存储和共享数据。它提供了一种在用户会话中跟踪状态的机制。
我们用这个方法判断登录状态,完成登录后,登录信息会储存在session,如果检测不到登录信息,就返回登录页面。
python
@bp.route('/logout')
def logout():
session.clear()
return redirect('/login.html')
有登录自然也要有登出,登出功能很简单,清除session中的信息即可。
在完成这些功能后,我们还要注册蓝图。在app.py中,写上:
python
from blueprints.login import bp as login_bp
app.register_blueprint(login_bp)
这样我们就配置了一个基本的flask项目。
完整的app.py代码:
python
from flask import Flask, render_template
from config import Config
from models import db
app = Flask(__name__)
app.secret_key = "QWERTYUIOP" # 对用户信息加密
# 引入数据库的登陆配置
app.config.from_object(Config)
# 把数据库初始化,导入登陆信息
db.__init__(app)
# 导入蓝图
from blueprints.login import bp as login_bp
app.register_blueprint(login_bp)
@app.route("/index.html")
def hello_world():
return render_template("/index.html")
if __name__ == "__main__":
app.run(debug="true", host="127.0.0.1")