Flask搭建网站
Cemon_Liu Lv5

Flask 搭建网站记录

建站目的

主要目的是用于维护资料的方便性。可以加一些验证减少人员的错误。

  1. 自动生成新的id,而不是靠人去自己找,杜绝重复
  2. 资料放在db,不会存在太多版本,资料是一致的
  3. 有上传和下载excel的功能,方便批量生成ID
  4. 有query功能,可以针对特定的资料进行编辑

文件目录

1
2
3
4
5
6
7
8
9
10
11
12
13
-app
- templates
- login.html
- index.html
- base.html
- upload.html
- query.html
- run.py
- query.py
- upload.py
- db.py
- auth.py

使用的功能

Blueprint

由于有好几个功能,最初的设计是全部放到一个主文件里面去。但是由于后面功能的增加,感觉不是太便捷。所以修改为使用蓝图进行配置。

1
2
3
4
5
6
7
8
9
10
import upload
import auth
import query

app.register_blueprint(upload.bp)
app.register_blueprint(auth.bp)
app.register_blueprint(query.bp)

auth.py 配置
bp = Blueprint('auth', __name__)

配置的时候比较简单,需要注意的是使用的时候要修改一些URL的引用。比如我auth.py 里面有个login 方法。如果未登录时,都要跳转回这里,需要使用redirect(url_for('auth.login'))

在每个文件里面可以是用同样的变量名bp,这样比较方便在主函数的调用注册。

db的使用

最初用的Pymysql 可以做SQL的简单增删改查。但是处理文件时,我使用了pandas库,而pandas默认只能支持sqlalchemy。所以在切分文件时,改成了全部使用sqlalchemy.

DB的初始化是参考官网的一个sample去初始化的。这里的调试遇到的最大问题。就是如果在主函数初始化,在其他文件去调用DB时,会报循环引用错误。就是app.py import upload.py, 而upload.py又引用的app.py里面的一个函数或者变量。最终导致一直报错。这种情形如果都写一个文件里面,不会出现。

解决方式是,在主函数里面,初始化DB db.init_db(app)。原始范例里面init_db_command 是一个命令行命令,当它被执行时,Flask 会自动创建并推送应用上下文,因此在这个命令中调用 init_db 不会有上下文问题。而如果要直接使用init_db函数只是注册了命令,实际的数据库初始化是在命令行调用时执行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

from flask import g
from sqlalchemy import create_engine

def get_db():
"""Connect to the application's configured database. The connection
is unique for each request and will be reused if this is called
again.
"""
if "db" not in g:
g.db = create_engine("mysql+pymysql://root:mysql@localhost/powerbi")
return g.db

def close_db(e=None):
"""If this request connected to the database, close the
connection.
"""
db = g.pop("db", None)
if db is not None:
db.close()

def init_db(app):
"""Clear existing data and create new tables."""
with app.app_context()
db = get_db()

# with current_app.open_resource("schema.sql") as f:
# db.executescript(f.read().decode("utf8"))


当我们在其他文件需要引用数据库时,直接import这个db文件的get_db方法即可。返回的是一个SQLAlchemy的engine

1
2
from db import get_db
db=get_db()

其他文件的逻辑实现

这里实现就比较简单的,大多是数据的增删改查。附上几个简单的用法。

  • 搭配pandas使用

    1
    2
    3
    4
    5
    # 使用pandas查询资料获取结果
    query = "SELECT * FROM dpn_status WHERE Substitute = %(substitute_id)s"
    params = {'substitute_id': id}
    results = pd.read_sql_query(query, con=db_engine, params=params)
    print(results)
  • 直接执行sql,需要注意SQL语句要搭配text()函数,不然无法执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
with db.connect() as conn:
query = text(
'''SELECT * FROM dpn_status WHERE Substitute = :sub LIMIT 1'''
)
result = conn.execute(query, {
'sub': substitutes[0]
}).fetchone()
print(result)
conn.execute(
text(
'''INSERT INTO dpn_status (DPN, 71PN,Substitute,Model,Region,Series,MP,EOP,EOW,WarrantyPeriod) VALUES (:DPN,:71PN,:Substitute,:Model,:Region,:Series,:MP,:EOP,:EOW,:WarrantyPeriod)'''
), {
"DPN": dpns[i],
"71PN": pn71s[i],
"Substitute": substitutes[i],
"Model": result[4],
"Region": regions[i],
"Series": result[6],
"MP": result[7],
"EOP": result[8],
"EOW": result[9],
"WarrantyPeriod": result[10]
})
conn.commit()
  • 删除资料,参数的搭配使用
1
2
3
query = text("DELETE FROM dpn_status where id = :id")
result = db_engine.connect().execute(query, {'id': id})

不足和思考

整体实现这个功能大约用了两周的时间。对于框架的使用还是不够熟悉,特别是数据库的初始化部分。现在回想一下,整个思路清晰多了。当然这里还有一些不足,比如我的登录验证是使用的明文密码存储来验证。文件的版本管控没有搭配git。

 评论
评论插件加载失败
正在加载评论插件
由 Hexo 驱动 & 主题 Keep
访客数 访问量