若你对Web开发不够了解,可以先看一下:用Python进行Web开发——基础介绍
1 Flask 概述
Web Framework:Web Application Framework(Web应用程序框架)或简单的Web Framework(Web框架)表示一个库和模块的集合,使Web应用程序开发人员能够编写应用程序,而不必担心协议,线程管理等低级细节。
Flask:一个用Python编写的Web应用程序框架。 它由 Armin Ronacher 开发,他领导一个名为Pocco的国际Python爱好者团队。 Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目。
WSGI:Web Server Gateway Interface(Web服务器网关接口,WSGI)已被用作Python Web应用程序开发的标准。 WSGI是Web服务器和Web应用程序之间通用接口的规范。
Werkzeug:它是一个WSGI工具包,它实现了请求,响应对象和实用函数。 这使得能够在其上构建web框架。 Flask框架使用Werkzeug作为其基础之一。
jinja2:Python的一个流行的模板引擎。Web模板系统将模板与特定数据源组合以呈现动态网页。
Flask通常被称为微框架。 它旨在保持应用程序的核心简单且可扩展。Flask没有用于数据库处理的内置抽象层,也没有形成验证支持。相反,Flask支持扩展以向应用程序添加此类功能。
2 Flask 应用
Hello.py:
from flask import Flask # 必须在项目中导入Flask模块。 Flask类的一个对象是我们的WSGI应用程序。
app = Flask(__name__) # Flask构造函数使用当前模块(__name __)的名称作为参数。
@app.route('/')
def hello_world():
return 'Hello World'
if __name__ == '__main__':
app.run()
Flask类的 route()
函数是一个装饰器,它告诉应用程序哪个URL应该调用相关的函数。
app.route(rule, options)
- rule 参数表示与该函数的URL绑定。
- options 是要转发给基础Rule对象的参数列表。
在上面的示例中,'/ ' URL
与hello_world()
函数绑定。因此,当在浏览器中打开web服务器的主页时,将呈现该函数的输出。
最后,Flask类的run()
方法在本地开发服务器上运行应用程序。
app.run(host, port, debug, options)
- host:要监听的主机名。 默认为127.0.0.1(localhost)。设置为“0.0.0.0”以使服务器在外部可用
- port:默认值为5000
- debug:默认为false。 如果设置为true,则提供调试信息
- options:要转发到底层的Werkzeug服务器。
调试模式:
通过调用run()
方法启动Flask应用程序。但是,当应用程序正在开发中时,应该为代码中的每个更改手动重新启动它。为避免这种不便,应启用调试支持。如果代码更改,服务器将自行重新加载。它还将提供一个有用的调试器来跟踪应用程序中的错误(如果有的话)。
在运行或将调试参数传递给run()
方法之前,通过将application对象的debug属性设置为True来启用Debug模式。
app.debug = True
app.run()
app.run(debug = True)
3 Flask 路由
现代Web框架使用路由技术来帮助用户记住应用程序URL。可以直接访问所需的页面,而无需从主页导航。
Flask中的route()
装饰器用于将URL绑定到函数。例如:
@app.route(‘/hello’)
def hello_world():
return ‘hello world’
在这里,URL '/ hello'
规则绑定到hello_world()
函数。 因此,如果用户访问http:// localhost:5000 / hello URL
,hello_world()
函数的输出将在浏览器中呈现。
application对象的add_url_rule()
函数也可用于将URL与函数绑定,如上例所示,使用route()
。
装饰器的目的也由以下表示:
def hello_world():
return ‘hello world’
app.add_url_rule(‘/’, ‘hello’, hello_world)
4 Flask 变量规则
通过向规则参数添加变量部分,可以动态构建URL。此变量部分标记为<variable-name>
。它作为关键字参数传递给与规则相关联的函数。
在以下示例中,route()
装饰器的规则参数包含附加到URL '/hello'
的<name>
。在浏览器中输入http://localhost:5000/hello/w3cschool
作为URL,则’w3cschool’将作为参数提供给hello()
函数。
from flask import Flask
app = Flask(__name__)
@app.route('/hello/<name>')
def hello_name(name):
return 'Hello %s!' % name
if __name__ == '__main__':
app.run(debug = True)
除了默认字符串变量部分之外,还可以使用以下转换器构建规则:
- int:接受整数
- float:对于浮点值
- path:接受用作目录分隔符的斜杠
在下面的代码中,使用了所有这些构造函数:
from flask import Flask
app = Flask(__name__)
@app.route('/blog/<int:postID>')
def show_blog(postID):
return 'Blog Number %d' % postID
@app.route('/rev/<float:revNo>')
def revision(revNo):
return 'Revision Number %f' % revNo
if __name__ == '__main__':
app.run()
Flask的URL规则基于Werkzeug的路由模块。这确保形成的URL是唯一的,并且基于Apache规定的先例。
考虑以下脚本中定义的规则:
from flask import Flask
app = Flask(__name__)
@app.route('/flask')
def hello_flask():
return 'Hello Flask'
@app.route('/python/')
def hello_python():
return 'Hello Python'
if __name__ == '__main__':
app.run()
这两个规则看起来类似,但在第二个规则中,使用斜杠(/)。因此,它成为一个规范的URL,使用 /python
或 /python/
返回相同的输出。但是,如果是第一个规则,/flask/ URL
会产生“404 Not Found”页面。
5 Flask URL构建
url_for()
函数对于动态构建特定函数的URL非常有用。该函数接受函数的名称作为第一个参数,以及一个或多个关键字参数,每个参数对应于URL的变量部分。
以下脚本演示了如何使用url_for()
函数:
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route('/admin')
def hello_admin():
return 'Hello Admin'
@app.route('/guest/<guest>')
def hello_guest(guest):
return 'Hello %s as Guest' % guest
@app.route('/user/<name>')
def hello_user(name): # 接受来自URL的参数的值
if name =='admin': # 检查接收的参数是否与'admin'匹配
return redirect(url_for('hello_admin')) # 匹配,则使用url_for()将应用程序重定向到hello_admin()函数
else:
return redirect(url_for('hello_guest',guest = name)) # 否则重定向到将接收的参数作为guest参数传递给它的hello_guest()函数
if __name__ == '__main__':
app.run(debug = True)
6 Flask HTTP方法
Http协议是万维网中数据通信的基础。在该协议中定义了从指定URL检索数据的不同方法。
以下是不同的http方法:
- GET:以未加密的形式将数据发送到服务器。最常见的方法。
- HEAD:和GET方法相同,但没有响应体。
- POST:用于将HTML表单数据发送到服务器。POST方法接收的数据不由服务器缓存。
- PUT:用上传的内容替换目标资源的所有当前表示。
- DELETE:删除由URL给出的目标资源的所有当前表示。
默认情况下,Flask路由响应GET请求。但是,可以通过为route()
装饰器提供方法参数来更改此首选项。
为了演示在URL路由中使用POST方法,首先创建一个HTML表单,并使用POST方法将表单数据发送到URL。
将以下脚本另存为login.html:
<html>
<body>
<form action = "http://localhost:5000/login" method = "post">
<p>Enter Name:</p>
<p><input type = "text" name = "nm" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
</body>
</html>
现在在Python shell中输入以下脚本:
from flask import Flask, redirect, url_for, request
app = Flask(__name__)
@app.route('/success/<name>')
def success(name):
return 'welcome %s' % name
@app.route('/login',methods = ['POST', 'GET'])
def login():
if request.method == 'POST':
user = request.form['nm']
return redirect(url_for('success',name = user))
else:
user = request.args.get('nm')
return redirect(url_for('success',name = user))
if __name__ == '__main__':
app.run(debug = True)
开发服务器开始运行后,在浏览器中打开login.html,在文本字段中输入name,然后单击提交。
表单数据将POST到表单标签的action子句中的URL。
http://localhost/login
映射到login()
函数。由于服务器通过POST方法接收数据,因此通过以下步骤获得从表单数据获得的“nm”参数的值:
user = request.form['nm']
它作为变量部分传递给'/ success'
URL。浏览器在窗口中显示welcome消息。
在login.html中将方法参数更改为**‘GET’,然后在浏览器中再次打开它。服务器上接收的数据是通过GET**方法获得的。通过以下的步骤获得’nm’参数的值:
User = request.args.get(‘nm’)
这里,args是包含表单参数对及其对应值对的列表的字典对象。与’nm’参数对应的值将像之前一样传递到'/ success'
URL。
7 Flask 模板
在前面的实例中,视图函数的主要作用是生成请求的响应,这是最简单请求.实际上,视图函数有两个作用:
- 处理业务逻辑
- 返回响应内容
在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.
模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取。
使用真实值替换变量,再返回最终得到的字符串,这个过程称为**‘渲染’**
Flask 是使用 Jinja2 这个模板引擎来渲染模板
使用模板的好处:
- 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
- 而模板则取到视图函数的数据结果进行展示(视图展示方面)
- 代码结构清晰,耦合度低
7.1 模板基本使用
在项目下创建 templates 文件夹,用于存放所有模板文件,并在目录下创建一个模板文件 html 文件 hello.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我的模板html内容
</body>
</html>
创建视图函数,将该模板内容进行渲染返回:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('hello.html')
7.2 模板变量
代码中传入字符串,列表,字典到模板中:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
# 往模板中传入的数据
my_str = 'Hello Word'
my_int = 10
my_array = [3, 4, 2, 1, 7, 9]
my_dict = {
'name': 'xiaoming',
'age': 18
}
return render_template('hello.html',
my_str=my_str,
my_int=my_int,
my_array=my_array,
my_dict=my_dict
)
模板中代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我的模板html内容
<br />{{ my_str }}
<br />{{ my_int }}
<br />{{ my_array }}
<br />{{ my_dict }}
</body>
</html>
运行效果:
我的模板html内容
Hello Word
10
[3, 4, 2, 1, 7, 9]
{'name': 'xiaoming', 'age': 18}
7.3 示例代码
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
my_int = 18
my_str = 'curry'
my_list = [1, 5, 4, 3, 2]
my_dict = {
'name': 'durant',
'age': 28
}
# render_template方法:渲染模板
# 参数1: 模板名称 参数n: 传到模板里的数据
return render_template('hello.html',
my_int=my_int,
my_str=my_str,
my_list=my_list,
my_dict=my_dict)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>我是模板</h2>
{{ my_int }}
<br>
{{ my_str }}
<br>
{{ my_list }}
<br>
{{ my_dict }}
<hr>
<h2>模板的list数据获取</h2>
<hr>
{{ my_list[0] }}
<br>
{{ my_list.1 }}
<hr>
<h2>字典数据获取</h2>
<hr>
{{ my_dict['name'] }}
<br>
{{ my_dict.age }}
<hr>
<h2>算术运算</h2>
<br>
{{ my_list.0 + 10 }}
<br>
{{ my_list[0] + my_list.1 }}
</body>
</html>
8 Flask 静态文件
Web应用程序通常需要静态文件,例如 javascript 文件或支持网页显示的 CSS 文件。通常,配置Web服务器并为您提供这些服务,但在开发过程中,这些文件是从您的包或模块旁边的static文件夹中提供,它将在应用程序的/static
中提供。特殊端点static用于生成静态文件的URL。
在下面的示例中,在 index.html 中的HTML按钮的OnClick事件上调用 hello.js 中定义的 javascript 函数,该函数在Flask应用程序的“/”
URL上呈现。
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html")
if __name__ == '__main__':
app.run(debug = True)
index.html 的HTML脚本如下所示:
<html>
<head>
<script type = "text/javascript"
src = "{{ url_for('static', filename = 'hello.js') }}" ></script>
</head>
<body>
<input type = "button" onclick = "sayHello()" value = "Say Hello" />
</body>
</html>
Hello.js包含sayHello()
函数:
function sayHello() {
alert("Hello World")
}
9 Flask Request对象
来自客户端网页的数据作为全局请求对象发送到服务器。为了处理请求数据,应该从Flask模块导入。
Request对象的重要属性如下所列:
- Form - 它是一个字典对象,包含表单参数及其值的键和值对。
- args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
- Cookies - 保存Cookie名称和值的字典对象。
- files - 与上传文件有关的数据。
- method - 当前请求方法。
10 Flask 将表单数据发送到模板
我们可以在 URL 规则中指定 http 方法。触发函数接收的 Form 数据可以以字典对象的形式收集它,并将其转发到模板,以在相应的网页上呈现它。
在以下示例中,'/'
URL 会呈现具有表单的网页(student.html)。填入的数据会发布到触发 result()
函数的 '/result'
URL。
result()
函数收集字典对象中的 request.form 中存在的表单数据,并将其发送给 result.html。
该模板动态呈现表单数据的 HTML 表格。
下面给出的是应用程序的 Python 代码:
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/')
def student():
return render_template('student.html')
@app.route('/result',methods = ['POST', 'GET'])
def result():
if request.method == 'POST':
result = request.form
return render_template("result.html",result = result)
if __name__ == '__main__':
app.run(debug = True)
下面给出的是 student.html 的 HTML 脚本:
<form action="http://localhost:5000/result" method="POST">
<p>Name <input type = "text" name = "Name" /></p>
<p>Physics <input type = "text" name = "Physics" /></p>
<p>Chemistry <input type = "text" name = "chemistry" /></p>
<p>Maths <input type ="text" name = "Mathematics" /></p>
<p><input type = "submit" value = "submit" /></p>
</form>
下面给出了模板( result.html )的代码:
<!doctype html>
<table border = 1>
{% for key, value in result.items() %}
<tr>
<th> {{ key }} </th>
<td> {{ value }}</td>
</tr>
{% endfor %}
</table>
运行 Python 脚本,并在浏览器中输入 URL http://localhost:5000/
。
当点击提交按钮时,表单数据以 HTML 表格的形式呈现在 result.html 上。
11 Flask Cookies
Cookie 以文本文件的形式存储在客户端的计算机上。其目的是记住和跟踪与客户使用相关的数据,以获得更好的访问者体验和网站统计信息。
Request对象包含 Cookie 的属性。它是所有cookie变量及其对应值的字典对象,客户端已传输。除此之外,cookie还存储其网站的到期时间,路径和域名。
在Flask中,对cookie的处理步骤为:
- 设置cookie:
设置cookie,默认有效期是临时cookie,浏览器关闭就失效。可以通过 max_age 设置有效期, 单位是秒。
resp = make_response("success") # 设置响应体
resp.set_cookie("w3cshool", "w3cshool", max_age=3600)
2.获取cookie
获取cookie,通过 request.cookies 的方式, 返回的是一个字典,可以获取字典里的相应的值。
cookie_1 = request.cookies.get("w3cshool")
3.删除cookie
这里的删除只是让cookie 过期,并不是直接删除cookie。删除cookie,通过delete_cookie()
的方式, 里面是cookie的名字。
resp = make_response("del success") # 设置响应体
resp.delete_cookie("w3cshool")
以下为Flask Cookies的简单示例:
from flask import Flask, make_response, request
app = Flask(__name__)
@app.route("/set_cookies")
def set_cookie():
resp = make_response("success")
resp.set_cookie("w3cshool", "w3cshool",max_age=3600)
return resp
@app.route("/get_cookies")
def get_cookie():
cookie_1 = request.cookies.get("w3cshool") # 获取名字为Itcast_1对应cookie的值
return cookie_1
@app.route("/delete_cookies")
def delete_cookie():
resp = make_response("del success")
resp.delete_cookie("w3cshool")
return resp
if __name__ == '__main__':
app.run(debug=True)
设置cookies:
运行应用程序,在浏览器中输入 127.0.0.1:5000/set_cookies
来设置cookies,设置 cookies 的输出如下所示:
获取cookie:
根据视图函数中相对应的路径,输入 http://127.0.0.1:5000/get_cookies
,读回 cookies 的输出如下所示:
删除cookie:
根据视图函数中相对应的路径,输入 http://127.0.0.1:5000/delete_cookies
,删除 cookies (只是让 cookie 过期) 的输出如下所示:
12 Flask Sessions 会话
与Cookie不同,Session(会话)数据存储在服务器上。会话是客户端登录到服务器并注销服务器的时间间隔。需要在该会话中保存的数据会存储在服务器上的临时目录中。
为每个客户端的会话分配会话ID。会话数据存储在cookie的顶部,服务器以加密方式对其进行签名。对于此加密,Flask应用程序需要一个定义的SECRET_KEY。
Session对象也是一个字典对象,包含会话变量和关联值的键值对。例如,要设置一个’username’会话变量:Session[‘username’] = ’admin’
要释放会话变量,使用pop()
方法:session.pop('username', None)
以下代码是Flask中的会话工作的简单演示。URL'/'
只是提示用户登录,因为未设置会话变量'username'
。
@app.route('/')
def index():
if 'username' in session:
username = session['username']
return 'Logged in as ' + username + '<br>' + \
"<b><a href = '/logout'>click here to log out</a></b>"
return "You are not logged in <br><a href = '/login'></b>" + \
"click here to log in</b></a>"
当用户浏览到“/login”
login()视图函数时,因为它是通过GET方法调用的,所以将打开一个登录表单。
表单发送回'/login'
,现在会话变量已设置。应用程序重定向到'/'
。此时会话变量'username'
被找到。
@app.route('/login', methods = ['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action = "" method = "post">
<p><input type = text name = username/></p>
<p<<input type = submit value = Login/></p>
</form>
'''
应用程序还包含一个logout()
视图函数,它会弹出’username
'会话变量。因此,'/'
URL再次显示开始页面。
@app.route('/logout')
def logout():
# remove the username from the session if it is there
session.pop('username', None)
return redirect(url_for('index'))
运行应用程序并访问主页。(确保设置应用程序的secret_key)
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
app.secret_key = 'any random string’
13 Flask 重定向和错误
Flask类有一个redirect()
函数。调用时,它返回一个响应对象,并将用户重定向到具有指定状态代码的另一个目标位置。
redirect()
函数的原型如下:Flask.redirect(location, statuscode, response)
- location:应该重定向响应的URL。
- statuscode:发送到浏览器标头,默认为302。
- response:用于实例化响应。
以下状态代码已标准化:
- HTTP_300_MULTIPLE_CHOICES
- HTTP_301_MOVED_PERMANENTLY
- HTTP_302_FOUND
- HTTP_303_SEE_OTHER
- HTTP_304_NOT_MODIFIED
- HTTP_305_USE_PROXY
- HTTP_306_RESERVED
- HTTP_307_TEMPORARY_REDIRECT
默认状态代码为302,表示’found’。
Flask类具有带有错误代码的abort()
函数:Flask.abort(code)
Code参数采用以下值之一:
- 400 - 用于错误请求
- 401 - 用于未身份验证的
- 403 - Forbidden
- 404 - 未找到
- 406 - 表示不接受
- 415 - 用于不支持的媒体类型
- 429 - 请求过多