Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

Gray-Ice

个人博客兼个人网站

之前曾学过flask,但是快要忘光了,而且也没有做笔记,这次重温一遍,就当是初学了。
本篇是在W3Cschool上学习的,链接:<a href=”https://www.w3cschool.cn/flask/flask_application.html"W3Cschool>

flask的安装与应用

输入以下命令来安装flask:

1
pip3 install flask

然后新建一个py文件:

1
vim flask_try.py

flask_try.py是文件名,你可以随便起。

然后编辑其中内容,每行代码的具体作用看注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 导入flask
from flask import Flask

# 实例化
app = Flask(__name__)

# route是个装饰器,用来指定访问哪个路由时应该调用哪个函数
@app.route('/')
def hello_world():
# 返回一个helloworld
return 'Hello World'

if __name__ == '__main__':
# 开启debug模式
app.debug = True
# 运行
app.run()

其中app.debug是可选的,开启debug用来在更改py文件的时候同步刷新flask服务。app.run中可以填入一些参数,如:app.run(host, port, debug, options)。
host指要监听的主机名,默认为127.0.0.1(localhost)。port是端口号,默认为5000,options是要转发到底层的Werkzeug服务器。
关于路由,如果你不想要使用装饰器的方式来写,也可以这么写:

1
app.add_url_rule('/', 'hello',hello_world)

其中’/‘是路由,’hello’似乎是名字, 具体作用我也不太清楚,但是如果不加上hello(任意字符串)就会报一个typeError的错误,hello_world是函数名。
那么想要运行flask,只需要输入:

1
python3 flask_try.py

即可运行。

flask变量规则

关于变量规则,w3cschool是这么说的:”通过向规则参数添加变量部分,可以动态构建url,此变量部分标记为,它作为关键字参数传递给与规则相关联的函数”。如果听不懂也没有关系,实践一下就明白了。那么下面是直接贴代码:

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


app = Flask(__name__)

# <fire>即为变量
@app.route('/<fire>')
def hello_world(fire):
return 'Hello %s' % fire


if __name__ == '__main__':
app.debug = True
app.run()

其中fire为变量。编辑完成后我们开启flask服务,访问127.0.0.1:5000/water会看到如下内容:
Hello water

除了使用字符串变量部分之外,还可以使用int,float和path。
w3cschool中是这么说的:

1
2
3
int 接受整数
float 对于浮点值
path 接受用作目录分隔符的斜杠

博主作为一个小白和一个理解能力奇差的人,除了int之外float和path都没看懂。但是这不妨碍我们继续进行下去。
先来看int和float的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

m flask import Flask


app = Flask(__name__)

# 这是int的传参
@app.route('/int/<int:fire>')
def hello_world(fire):
return 'Hello %d' % fire

# 这是float的传参
@app.route('/float/<float:fnum>')
def releasefloat(fnum):
return 'This is a float number %f' % fnum


if __name__ == '__main__':
app.debug = True
app.run()

如此定义好之后,访问127.0.0.1:5000/int/1可以看到:Hello 1。
访问127.0.0.1:5000/float/1.1可以看到:This is a float number 1.100000。
注意,如果访问127.0.0.1:5000/float/1,则会出现not found,这是因为1并不是浮点数。同理,访问127.0.0.1:5000/int/1.1也会出现not found,相信看到这里大家已经很明白了,int和float是指定接受参数的类型,如果不是符合要求的参数,则不会正确匹配到指定的函数。

那么下面要说的就是path了。
先看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask


app = Flask(__name__)

@app.route('/try')
def hello_world():
return 'Hello'

@app.route('/fire/')
def hello_fire():
return 'Hello fire'

if __name__ == '__main__':
app.debug = True
app.run()

可以看到,/try是一个url,/fire/也是一个url。运行flask,访问/try的时候,可以看到Hello,但是访问/try/的时候,则出现了not found的提示。但是访问/fire的时候,url则自动变成了/fire/,并且出现了:Hello fire 。为社么会出现这样的情况呢?用W3Cschool中的话来说,类似于/fire/的URL是一个规范URL,因此,访问/fire或/fire/返回相同的输出。

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
26
from flask import Flask, redirect, url_for


app = Flask(__name__)

@app.route('/try/')
def hello_water():
return 'I am water'

@app.route('/fire/<water>')
def hello_fire(water):
if water == 'water':
# 如果接受的参数是'water',则重定向到hello_water(即/try/)
return redirect(url_for('hello_water'))
else:
# 如果接受到的是其他的参数,则重定向到not_water(即/water/<name>),并且传递参数(注意看清括号)
return redirect(url_for('not_water', name=water))


@app.route('/water/<name>')
def not_water(name):
return 'I am not water, I am %s' % name
if __name__ == '__main__':
app.debug = True
app.run()

在这里我们使用redirect来进行页面重定向。在函数hello_fire(即路由/fire//)中进行了判断,如果传递过来的参数是’water’,则重定向到/try/,否则则带参跳转到not_water(即路由/water/)。
首先访问url: 127.0.0.1:5000/fire/water,可以看到显示出了:I am water,并且可以看到路由变成了127.0.0.1:5000/try/(如果路由没有变就刷新一下页面)。接着我们访问127.0.0.1:5000/fire/water1,页面显示出:I am not water, I am water1。路由也变成了127.0.0.1:5000/water/water1。相信看到这里,大家都会明白了,那么我们就进入下一小题。

HTTP方法

下面的全部内容几乎都来自W3Cschool:
Http协议是万维网中数据通信的基础。在该协议中定义了从指定URL检索数据的不同方法。
下面总结了不同的http方法:

1.GET 以未加密的形式将数据发送到服务器,最常见的方法。
2.HEAD 和GET方法相同,但没有响应体。
3.POST 用于将HTML表单数据发送到服务器。POST方法接收的数据不由服务器缓存。
4.PUT 用上传的内容替换目标资源的所有当前表示。
5.DELETE 删除由URL给出的目标资源的所有当前表示。

默认情况下,Flask路由响应GET请求,但是,可以通过为route()装饰器提供方法参数来更改此首选项。
为了演示URL路由中使用POST方法,首先让我们创建一个HTML表单,并使用POST方法将表单数据发送到URL。
将以下代码存入

1
2
3
4
5
6
7
8
9
10
11
12
<html>
<body>

<form action = "http://localhost:5000/try" method = "post">
<p>Enter Name:</p>
<p><input type = "text" name = "nm" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>

</body>
</html>

编辑py文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from flask import Flask, redirect, url_for, request


app = Flask(__name__)

@app.route('/try', methods=['POST', 'GET'])
def hello_water():
# 如果请求方式为POST,从表单数据中获取参数为nm的值并返回一段字符串
if request.method == 'POST':
user = request.form['nm']
return 'You are %s' % user
# 如果请求方式为GET,获取参数nm的值
# args是包含表单参数对及其对应值对的列表的字典对象
elif request.method == 'GET':
user = request.args.get('nm')
return 'You got me, %s' % user
# 其他情况(其实在只有GET和POST的情况下这条语句是不会执行的)
else:
return 'How did you request me?'

if __name__ == '__main__':
app.debug = True
app.run()

接下来用浏览器打开刚才编辑的html文件,输入好内容之后提交,页面会跳转到localhost:5000/try,页面内容为 You are 加上你输入的内容。接下来直接访问localhost:5000/try?nm=1,或者将html文件中表单提交方式改为get。如果是通过访问页面localhost:5000/try?nm=1的URL来访问页面的话,内容为You got me, 1。如果是使用GET方法的表单提交的话,内容为You got me, 你输入的内容。

模板

可以以HTML的形式返回绑定到某个URL的函数的输出,看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask, redirect, url_for, request


app = Flask(__name__)

@app.route('/')
def hello_water():
return '<html><body><h1>Good morning</h1></body></html>'

if __name__ == '__main__':
app.debug = True
app.run()

访问127.0.0.1:5000,可以看到以h1标签形式呈现的Good Morning字符串。
但是,从Python代码生成HTML内容很麻烦,尤其是在需要放置变量数据和Python语言元素(如条件或循环时)。这需要经常从HTML中转义。
这是可以利用Flask所基于的Jinja2模板引擎的地方。而不是从函数返回硬编码HTML,可以通过render_template()函数呈现HTML文件。 –W3Cschool

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


app = Flask(__name__)

@app.route('/')
def hello_water():
return render_template('try1.html')

if __name__ == '__main__':
app.debug = True
app.run()

接下来,新建一个叫做templates的文件夹,并且在其中新建一个叫做try1.html的文件(html文件叫做什么都行,只要和py文件中写的名字一样都可以,但是文件夹必须叫做templates)。注意,文件夹要和py文件同级。

1
2
3
mkdir templates
cd templates
vim try1.html

下面是html的代码:

1
2
3
4
5
6
7
8
<html>
<head>
</head>
<body>
<h1>Hello {{name}}</h1>
</body>
<html>

运行flask,访问127.0.0.1:5000,就可以看到一个h1标题的Welcome to THis Page的字符串。
那么也许你会有问题,为什么要将html文件放进一个叫做templates的文件夹里呢,为什么我不可以将html文件放在py文件的同级目录下?
很遗憾我已经试过了,放在同级目录下就算将’try1.html’改为’./try1.html’也是行不通的。上面引用自W3Cschool的那句话已经说明白了,这是引用的Jinja2模板引擎,既然是别人制定好的东西就要跟着别人走,这个问题就像是在问”python为什么不叫phython”一样,得到的答案是这是别人定的。
好了,那么言归正传,除了能够直接返回html之外,也可以在html添加一些自己想要添加的内容,比如将html这样写:

1
2
3
4
5
6
7
<html>
<body>

<h1>Hello {{ name }}!</h1>

</body>
</html>

然后稍稍更改一下py文件:

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


app = Flask(__name__)

@app.route('/root/<user>')
def hello_water(user):
return render_template('./try1.html', name=user)

if __name__ == '__main__':
app.debug = True
app.run()

运行py文件,访问127.0.0.1:5000/root/fire, 会看到以h1标题展现的Hello fire。

1
2
3
4
5
{{name}}是一个占位符,Jinja2模板引擎用以下分隔符从HTML转义。
{% ... %}用于语句
{{ ... }}用于表达式打印到模板输出
{# ... #}用于未包含在模板输出中的注释
# ... ##用于行语句

关于这块的内容我就不多说了,我主要是想要使用flask+vue运行项目,所以使用模板对我应该用处不大。想要了解更多可以访问W3Cschool,我这篇博客就是参照它上面的内容写出来的。

Request对象

可以查看官方文档响应对象来深入了解,这里我打算从W3Cschool上搬一段。

1
2
3
4
5
6
7
8
9
10
11
12
来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。
Request对象的重要属性如下所列:

Form - 它是一个字典对象,包含表单参数及其值的键和值对。

args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。

Cookies - 保存Cookie名称和值的字典对象。

files - 与上传文件有关的数据。

method - 当前请求方法。

其实我觉得这一段设置的有点莫名其妙了,我认为它应该在HTTP方法那一节才对。不过官方文档上这一节也是在这个地方。

Cookies

Cookie以文本文件的形式存储在客户端的计算机上,其目的是记住和跟踪与客户端使用相关的数据,以获得更好的访问者体验或网站统计信息。
Request对象包含Cookie的属性。它是所有cookie变量及其对应值的字典对象,客户端已传输。除此之外,cookie还存储其网站的到期时间,路径和域名。 –来自W3Cschool
其实我很少用到Cookie,所以这一节也就略过,感兴趣的可以在W3Cschool上面查看。

Flask跨域

参考自让Flask支持跨域–邻居的尾巴。感谢作者提供的解决方法~
首先,安装flask-cors模块:

1
pip3 install flask-cors

然后请看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from flask import Flask, redirect, url_for, request
from flask_cors import CORS
import json
app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def hello_world():
return json.dumps({
'code': 200,
'msg': 'Good'
})

if __name__ == '__main__':
# 跨域
CORS(app, supports_credentials=True)
app.debug = True
app.run()


跨域就是这样~~

评论



愿火焰指引你