目录:
【Flask学习笔记:一】开发环境部署
【Flask学习笔记:二】Flask 入门基础知识
【Flask学习笔记:三】Flask 中的 request、response
【Flask学习笔记:四】Flask 应用和请求上下文
【Flask学习笔记:五】Jinja2 模板引擎
【Flask学习笔记:六】Flask 蓝图
【Flask学习笔记:七】Flask - WTF 处理表单
【Flask学习笔记:八】Flask 中的 cookie、session
【Flask学习笔记:九】Flask-SQLAlchemy
【Flask学习笔记:二】Flask 入门基础知识
Flask 一个轻量级的 WSGI Web 应用程序框架,虽然其核心非常小,但是该 Web 框架简约而不简单,具有很强的扩展能力。Flask基于 Werkzeug WSGI 工具包和 Jinja2 模板引擎,都是由 Armin Ronacher 开发。
一、第一个 Flask Web 程序
1.在 Pycharm 中安装 Flask 框架
在终端输入:
conda install flask
2.创建一个最小的应用
from flask import Flask # 导入了 Flask 类
app = Flask(__name__) # __name__ 代表的是这个模块本身的名称
@app.route('/hello') # 使用 route() 装饰器来告诉 Flask 触发函数的 URL,把 URL 和函数之间关系的程序定义为路由
def hello():
return 'hello world' # 返回需要在用户浏览器中显示的信息
if __name__ == '__main__':
app.run() # 通过 run 方法来启动 Flask 自身集成的服务器
在 Pycharm 中来运行这个应用
python demo.py
运行结果:
app.run() 中可以传入一些参数:
def run(self, host=None, port=None, debug=None, **options)
- host - IP地址,设置为 ‘0.0.0.0’ ,使服务器在外部也可以被访问,未指定则为127.0.0.1
- port - 端口地址,未指定则为5000
- debug - 是否开启调试模式,如果设置了调试模式,遇到错误控制台会输出具体错误信息,修改代码会自动重新提交给 Web 服务器
- options - 实际最后会调用 run_simple(),传递更多设置参数(例:threaded = True 开启多线程;更多参数设置参考 API文档
werkzeug.serving.run_simple(host, port, self, **options)
如下图设置参数:
app.run(host='0.0.0.0', port=8080, debug=True)
二、路由
客户端(例如 Web 浏览器)把请求发送给 Web 服务器, Web服务器再把请求发送给 Flask 应用实例。应用实例需要知道对每个 URL 的请求要运行哪些代码,所以保存了一个 URL 到 Python 函数的映射关系。处理 URL 和函数之间关系的程序称为路由。
1.使用 route() 装饰器来把函数绑定到 URL
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello, World'
index() 函数注册为应用根地址的处理程序。使用 app.route 装饰器注册视图函数是首选方法,但不是唯一方法。Flask 还支持一种更传统的方式:使用 app.add_url_rule() 方法。这个方法最简单的形式接受3个参数:URL、端点名(endpoint)和视图函数。下述示例使用 app.add_url_rule() 方法注册 index() 函数,其作用与前例相同:
def index():
return 'Index Page'
def hello():
return 'Hello, World'
app.add_url_rule('/', 'index', index)
app.add_url_rule('/hello', 'hello', hello)
2. URL传递参数(变量规则)
Flask 通过 URL 传递参数,通过把 URL 的一部分标记为 <variable_name>
就可以在 URL 中添加变量。标记的 部分会作为关键字参数传递给函数:
@app.route('/user/<username>')
def show_username(username):
return 'Hello %s!' % username
也可以通过使用 <converter:variable_name>
为变量指定规则:
string | 接受任何不包含斜杠的文本 |
---|---|
int | 接受正整数 |
float | 接受正浮点数 |
path | 类似 string ,但可以包含斜杠 |
uuid | 接受 UUID 字符串 |
例:
@app.route('/user/<int:user_id>')
def show_userid(user_id):
return 'user_id %s!' % user_id
注意: 定义数据类型的 URL 只能传对应类型的参数,错误的参数类型传递会产生 “404 Not Found” 页面。
3. 唯一的 URL
以下两条规则的不同之处在于是否使用尾部的斜杠。:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects 的 URL 尾部有一个斜杠, 访问没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜杠。
about 的 URL 没有尾部斜杠,如果访问这个 URL 时添加了尾部斜杠就会得到一个 404 错误。这样可以保证 URL 唯一,并帮助搜索引擎避免重复索引同一页面。
4.URL 反转 url_for 函数
要使用 url_for() 函数,需要使用 from flask import url_for 导入, url_for 接收的参数设置:
url_for(endpoint, **values)
endpoint | URL的端点(即函数的名字) |
---|---|
values | 接受任意个关键字参数,每个关键字参数对应 URL 中的变量 |
endpoint | URL的端点(即函数的名字) |
_external | 设置为True,则生成一个绝对URL |
_method | 设置此参数,则指定 HTTP 方法 |
例:
@app.route("/")
def hello():
return url_for('show_userid', user_id=2, _external=True, _method='POST')
@app.route('/user/<int:user_id>', methods=['POST'])
def show_userid(user_id):
return 'user_id %s!' % user_id
未设置 _external 返回相对路径:
设置 _external = True 返回绝对路径:
endpoint:
在flask框架中,我们经常会用到 endpoint,给路由指定规则,我们可以看下 app.route() 这个装饰器都做了些什么:
实际上 app.route 最终调的是 add_url_rule 这个函数
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
如果未设置 endpoint 值,会将视图函数的名称作为 endpoint,在此函数内会创建一个 Rule 的实例,然后存储在 app 下的 url_map 中,以 endpoint 为键值,对应视图函数 view_func,所以我们可以看出:这个url_map存储的是url与endpoint的映射。
当请求传来一个url的时候,会先通过rule找到 url_map 中的 endpoint,然后再根据 endpoint 再找到对应的view_func,所以当有请求来的时候,我们就能知道到底使用哪一个视图函数。
三、HTTP 方法
Web 应用使用不同的 HTTP 方法处理 URL 。当你使用 Flask 时,应当熟悉 HTTP 方法。 缺省情况下,一个路由只回应 GET 请求。 可以使用 route() 装饰器的 methods 参数来处理不同的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
四、页面跳转和重定向
用户在访问某个页面的时候,我们希望他登录后才能访问该页面,如果此时他没有登录,系统就让浏览器由当前页面跳转到登录页面,这里就涉及页面重定向问题。所谓页面重定向,就是用户在打开某个页面的时候,我们期望页面跳转到另一个指定的页面,让用户完成某种操作或执行某个动作。
使用 Flask 提供的 redirect() 函数可以重定向,该函数的功能就是跳转到指定的 URL。
例:
目录结构:
/demo.py
/templates
/login.html
/success.html
from flask import Flask, url_for, redirect, render_template, request
app = Flask(__name__)
app.config['DEBUG'] = True
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
username = request.form.get('username')
return render_template('success.html', username=username)
if __name__ == '__main__':
app.run(port=8080)
在浏览器输入地址 localhost:8080 跳转到登录界面,实现了重定向
五、静态文件的加载
静态文件的加载一般需要先新建文件夹 static, 在文件夹下再新建 css、 js 和 images 文件夹,在这些文件夹中存放 css、js、images,可以使用 url_for() 函数来实现:
例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
</head>
<body>
<div class="container">
<span>登录</span>
<form action="{{ url_for('login') }}" method="post">
<p>username: <input type="text" name="username" /></p>
<p>password: <input type="password" name="password" /></p>
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>
这里我们使用 url_for 加载我们的 style.css 样式文件、
六、消息闪现
请求完成后,有时需要让用户知道状态发生了变化,可以是确认消息、警告或者错误提醒。一个典型例子是,用户提交有一项错误的登录表单后,服务器发回的响应重新渲染登录表单,并在表单上面显示一个消息,提示用户名或密码无效。
Flask 本身内置这个功能,flash() 函数可实现这种效果。
from flask import Flask, flash, redirect, render_template, request, url_for
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != 'admin' or request.form['password'] != 'secret':
error = 'Invalid credentials'
else:
flash('You were successfully logged in')
return redirect(url_for('index'))
return render_template('login.html', error=error)
仅调用 flash() 函数并不能把消息显示出来,应用的模板必须渲染这些信息。Flask 把 get_flashed_messages() 函数开放给模板,用于获取并渲染闪现消息:
<!doctype html>
<title>My Application</title>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}{% endblock %}
七、钩子函数的使用
根据需要,有时候需要在正常执行代码的前、中、后时期,执行一段我们所需要的功能代码,实现这种功能的函数就称为钩子函数。钩子函数的实质就是用特定装饰器装饰的函数。
介绍四种钩子函数:
① before_first_request() 函数
只处理第一次请求之前执行,可以通过这个钩子添加服务器初始化任务。
②before_request() 函数
每一次请求之前可以执行某个特定功能的函数。一般可以用来检验用户请求是否合法、权限检查等场景。
③after_request() 函数
如果没有未处理的异常抛出,在每次请求之后执行。
④teardown_request() 函数
即使有未处理的异常抛出,也在每次请求之后执行。
在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量g。例如,before_request 处理程序可以从数据库中加载已登陆用户,并将其保存到 g.user 中。随后调用视图函数时,便可以通过 g.user 获取用户。