总述

2020年8月4日。是实训的第12天。
今天上午孟老师带我们回顾了过去在Django这一块所学的一些知识,然后开始讲授flask。完成从flask的创建到部署,再是路由、跨域、连接数据库等等任务。

Flask 是一个微型的 Python 开发的 Web 框架,基于Werkzeug WSGI工具箱和Jinja2模板引擎。 Flask使用BSD授权。 Flask也被称为“microframework”,因为它使用简单的核心,用extension增加其他功能。Flask没有默认使用的数据库、窗体验证工具。然而,Flask保留了扩增的弹性,可以用Flask-extension加入这些功能:ORM、窗体验证工具、文件上传、各种开放式身份验证技术。

通过今天的学习,我确实感受到了Flask比Django要简单一些。花费较少的精力和时间就能达到和Django同样的效果。但是即便如此,我依然决定在我的大作业上使用Django。因为就我自身而言,我对Django更加熟悉。

今天的知识把握程度还行,基于对Django的理解上再去学习Flask就没有那么难。但是对于ajax嵌套,我仍是有一些不明白的地方。

Flask的优势:

  • Flask是一个轻量级的可定制框架
  • 插件超级多,不用自己造轮子

新建Flask项目

在Pycharm中点击新建,选择Flask项目,即可完成项目的创建。

项目创建完毕后,可以看到如下的文件夹结构。Flask框架确实比Django框架要轻量得多。

运行测试

先来对主要的app.py的代码,作一些注释。

1
2
3
4
5
6
7
8
9
10
11
12
from flask import Flask

app = Flask(__name__)

# 路由不可重复,函数也不可重复。
@app.route('/') #装饰器路由
def hello_world(): #视图函数
return 'Hello World!'


if __name__ == '__main__':
app.run() #会在这里启动。所以Flask不用像Django一样输入命令行启动。直接运行即可。

运行的结果如下图所示。

一般,我们想要的数据,是json数据,在此引入一个包。

1
from flask import jsonify

有了这样一个包,

1
2
jsonify({'data':{'name':'Zorua','age':20}})
#等价于之前在Django的JsonResponse

测试效果

部署修改

现在这个站点是部署在本地的,如果部署在云服务器上,或需要修改端口。
可在app.run()中加入参数,如下所示。

1
app.run(host='0.0.0.0',port=8888)

这个效果不能马上生效,还需要添加新的配置。

选择Python,然后在右侧,名称写为app.py,Script Path为该文件的绝对路径。

最后在命令行键入python app.py即可生效。

DEBUG模式

Flask默认是没有开启debug模式的,开启debug模式有很多好处:

  • 可以帮助我们查找代码里面的错误
  • 每次修改代码不需要重新运行代码

为开启DEBUG模式,只需要在app.run()的参数中增加一个debug=True,或者在其下面加一句app.debug=True

1
2
app.run(debug=True,host='0.0.0.0',port=8888)
app.debug = True

前后端分离

添加新的路由

1
2
3
4
5
@app.route('/index') #装饰器路由
def hello_world(): # 视图函数
return render_template('index.html')
#为使用上面这个语句,需要引入包:
# from flask import render_template

再在templates文件夹中,新建一个index.html

运行查看一下效果:

请求类型

对于路由的请求类型,可以在装饰器的函数里面加一个参数methods=['GET','POST']

1
2
3
@app.route('/api',methods=['POST','GET']) #装饰器路由
def api(): # 视图函数
pass

如果想获取参数的话,需要引入一个包:

1
2
3
4
5
6
7
from flask import request
@app.route('/api',methods=['POST','GET']) #装饰器路由
def api(): # 视图函数
name = request.args.get('name')
age = request.args.get('age')
print(name)
return jsonify({'data':{'name':name,'age':age}})

之后和Django类似,使用request.args.get()函数来获取参数。
对于post请求,只需要把上面的args改成form就可以了。
即:

1
2
3
4
5
6
7
from flask import request
@app.route('/api',methods=['POST','GET']) #装饰器路由
def api(): # 视图函数
name = request.form.get('name')
age = request.form.get('age')
print(name)
return jsonify({'data':{'name':name,'age':age}})

跨域

引用包flask_cors,然后调用flask_cors.CORS(app)

1
2
import flask_cors
flask_cors.CORS(app)

跨域能够实现前后端分离:

  • 前端:对json数据进行渲染,ajax请求后台接口
  • 后端:数据打包json,提供可以被调用的api

ajax

和之前的Django类似,不同的地方在于url。

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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>wow</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
Wow awesome
</body>
<script>
$.ajax({
url:'http://127.0.0.1:8888/api',
type:'post',
dataType:'json',
data:{
name:'Zorua',
age:13
},
success:function(res){
console.log(res.data)
}
})
</script>
</html>

连接数据库

准备工作

先安装一个库。在命令行中键入pip install Flask-SQLAlchemy并按下回车键。

1
2
3
4
5
6
#数据库连接
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+os.path.join(BASEDIR,'data.sqlite')
'''
如果设置成 True(默认情况),Flask-SQLAlchemy将会追踪对象的修改并且发送信号 这需要额外的内存 如果不必要的话可以禁用它
'''
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False

创建数据库

1
2
3
4
5
6
7
db = SQLAlchemy(app)
class Info(db.Model):
id = db.Column(db.Integer,primary_key=True)
title = db.Column(db.String(255))
category = db.Column(db.String(60))
def __repr__(self):
return '<info.>%s ' % self.title


创建完毕后,再命令行中键入flask shell。

插入数据

1
2
3
4
info1 = Info(id=1,title='新闻1',category='娱乐新闻')
info2 = Info(id=2,title='新闻2',category='工作新闻')
db.session.add_all([info1,info2]) #将数据添加到会话
db.session.commit() #提交会话

查询数据

1
2
3
4
5
6
@app.route('/query',methods=['GET','POST']) #装饰器路由
def query():
results=Info.query.all()
for i in results:
print(i)
return jsonify({'data':'Success'})

更新数据

1
2
3
4
@app.route('/update',methods=['GET','POST']) #装饰器路由
def update():
Info.query.filter(Info.title=='新闻1').update({'category':'改后新闻'})
return jsonify({'data':'Success'})

删除数据

1
2
3
4
@app.route('/update',methods=['GET','POST']) #装饰器路由
def update():
Info.query.filter(Info.title=='新闻1').delete()
return jsonify({'data':'Success'})