一,调试模式
如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生错误时提供一个相当有用的调试器。
有两种途径来启用调试模式。一种是直接在应用对象上设置:
app.debug = True
app.run()
另一种是作为 run 方法的一个参数传入:
app.run(debug=True)
两种方法的效果完全相同。
默认是开启的。
二,route
route()装饰器把一个函数绑定到对应的 URL 上
如:
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
三,变量规则
要给 URL 添加变量部分,你可以把这些特殊的字段标记为 <variable_name> , 这个部分将会作为命名参数传递到你的函数。规则可以用 <converter:variable_name> 指定一个可选的转换器。
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id
转换器有下面几种:
int 接受整数
float 同 int ,但是接受浮点数
path 和默认的相似,但也接受斜线
四,唯一 URL / 重定向行为
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
第一种情况中,指向 projects 的规范 URL 尾端有一个斜线。这种感觉很像在文件系统中的文件夹。访问一个结尾不带斜线的 URL 会被 Flask 重定向到带斜线的规范 URL 去。
然而,第二种情况的 URL 结尾不带斜线,类似 UNIX-like 系统下的文件的路径名。访问结尾带斜线的 URL 会产生一个 404 “Not Found” 错误。
八,构造 URL
可以用 url_for()来给指定的函数构造 URL。它接受函数名作为第一个参数,也接受对应 URL 规则的变量部分的命名参数。未知变量部分会添加到 URL 末尾作为查询参数。
九,HTTP 方法
HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET请求,但是通过route()装饰器传递 methods参数可以改变这个行为。
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
HTTP 方法(也经常被叫做“谓词”)告知服务器,客户端想对请求的页面 做 些什么。下面的都是非常常见的方法:
GET
浏览器告知服务器:只 获取 页面上的信息并发给我。这是最常用的方法。
HEAD
浏览器告诉服务器:欲获取信息,但是只关心 消息头 。应用应像处理 GET 请求一样来处理它,但是不分发实际内容。在 Flask 中你完全无需 人工 干预,底层的 Werkzeug 库已经替你打点好了。
POST
浏览器告诉服务器:想在 URL 上 发布 新信息。并且,服务器必须确保 数据已存储且仅存储一次。这是 HTML 表单通常发送数据到服务器的方法。
PUT
类似 POST 但是服务器可能触发了存储过程多次,多次覆盖掉旧值。你可 能会问这有什么用,当然这是有原因的。考虑到传输中连接可能会丢失,在 这种 情况下浏览器和服务器之间的系统可能安全地第二次接收请求,而 不破坏其它东西。因为 POST 它只触发一次,所以用 POST 是不可能的。
DELETE
删除给定位置的信息。
OPTIONS
给客户端提供一个敏捷的途径来弄清这个 URL 支持哪些 HTTP 方法。 从 Flask 0.6 开始,实现了自动处理。
在 HTML4 和 XHTML1 中,表单只能以 GET 和 POST 方法提交到服务器。但是 JavaScript 和未来的 HTML 标准允许你使用其它所有的方法。
五,静态文件
动态 web 应用也会需要静态文件,通常是 CSS 和 JavaScript 文件。
只要在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。
给静态文件生成 URL ,使用特殊的 'static' 端点名:
url_for('static', filename='style.css')
这个文件应该存储在文件系统上的 static/style.css 。
六,模板渲染
Flask 配备了 Jinja2模板引擎。
你可以使用 render_template()方法来渲染模板。你需要做的一切就是将模板名和你想作为关键字的参数传入模板的变量。这里有一个展示如何渲染模板的简例:
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)
Flask 会在 templates 文件夹里寻找模板。所以,如果你的应用是个模块,这个文件夹应该与模块同级;如果它是一个包,那么这个文件夹作为包的子目录:
情况 1: 模块:
/application.py
/templates
/hello.html
情况 2: 包:
/application
/init.py
/templates
/hello.html
Jinja2模板实例:
更多访问http://docs.jinkan.org/docs/jinja2
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
在模板里,你也可以访问 request、session和 g对象, 以及 get_flashed_messages函数。
最起码,模板继承能使特定元素 (比如页眉、导航栏和页脚)可以出现在所有的页面。
七,访问请求数据
对于 Web 应用,与客户端发送给服务器的数据交互至关重要。在 Flask 中由全局的 request
对象来提供这些信息。如果你有一定的 Python 经验,你会好奇,为什么这个对象是全局的,为什么 Flask 还能保证线程安全。答案是环境作用域
八,环境局部变量
单元测试的最简单的解决方案是:用 test_request_context环境管理器。结合 with声明,绑定一个测试请求,这样你才能与之交互。下面是一个例子:
from flask import request
with app.test_request_context('/hello', method='POST'):
# now you can do something with the request until the
# end of the with block, such as basic assertions:
assert request.path == '/hello'
assert request.method == 'POST'
另一种可能是:传递整个 WSGI 环境给request_context方法:
from flask import request
with app.request_context(environ):
assert request.method == 'POST'
九,请求对象
首先从 flask 模块里导入它:
from flask import request
当前请求的 HTTP 方法可通过 method 属性来访问。通过:attr:~flask.request.form 属性来访问表单数据( POST 或 PUT 请求提交的数据)。这里有一个用到上面提到的那两个属性的完整实例:
@app.route('/login', methods=['POST', 'GET'])
def login():
error = None
if request.method == 'POST':
if valid_login(request.form['username'],
request.form['password']):
return log_the_user_in(request.form['username'])
else:
error = 'Invalid username/password'
# the code below is executed if the request method
# was GET or the credentials were invalid
return render_template('login.html', error=error)
当访问 form属性中的不存在的键会发生什么?会抛出一个特殊的 KeyError异常。你可以像捕获标准的 KeyError 一样来捕获它。 如果你不这么做,它会显示一个 HTTP 400 Bad Request 错误页面。所以,多数情况下你并不需要干预这个行为。
你可以通过 args属性来访问 URL 中提交的参数 ( ?key=value):
searchword = request.args.get('q', '')
推荐用 get 来访问 URL 参数或捕获 KeyError ,因为用户可能会修改 URL,向他们展现一个 400 bad request 页面会影响用户体验。
十一,文件上传
用 Flask 处理文件上传很简单。只要确保你没忘记在 HTML 表单中设置 enctype="multipart/form-data" 属性,不然你的浏览器根本不会发送文件。
已上传的文件存储在内存或是文件系统中一个临时的位置。你可以通过请求对象的 files
属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file
对象,但它还有一个save()方法,这个方法允许你把文件保存到服务器的文件系统上。这里是一个用它保存文件的例子:
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...
如果你要把文件按客户端提供的文件名存储在服务器上,那么请把它传递给 Werkzeug 提供的secure_filename函数:
from flask import request
from werkzeug import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...
十二,Cookies
可以通过 cookies属性来访问 Cookies,用响应对象的set_cookie方法来设置 Cookies。请求对象的 cookies 属性是一个内容为客户端提交的所有 Cookies 的字典。如果你想使用会话,请不要直接使用 Cookies。在 Flask 中,已经注意处理了一些 Cookies 安全细节。
读取 cookies:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
存储 cookies:
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
Cookies 是设置在响应对象上的。由于通常视图函数只是返回字符串,之后 Flask 将字符串转换为响应对象。如果你要显式地转换,你可以使用 make_response函数然后再进行修改。