文章目录
1. 基本
- 一个不叫flask.py的文件,因为这会与Flask冲突,然后使用python运行
# flaskr.py from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World' @app.route('/user/<username>') def show_user_profile(username): return 'User %s' % username @app.route('/post/<int:post_id>') def show_post(post_id): return 'Post %d' % post_id if __name__ == '__main__': # app.run() 调试模式,该文件只能从你自己的计算机上访问,网络中其它任何的地方都不能访问。只有加了host='0.0.0.0'才可以 # app.run(debug=True) 或者 app.debug=True 可以让应用在你修改了代码后自动的重启服务器。并且如果发生错误,它会提供一个有用的调试器。 # 其他调试器 http://www.pythondoc.com/flask/errorhandling.html#working-with-debuggers app.run(host='0.0.0.0', port=5000, debug=True)
- 现在浏览 http://127.0.0.1:5000/,你会看到你的 Hello World 问候。
- app.route指定接受的url,里面可以有int/float/string类型的转换器,形式是type:variable\。
- app.route(’/a/’)可以表示app.route(’/a’),但反过来不行,会404 not found
2. url_for使用
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index(): pass
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'GET':
show_the_log_form()
else:
do_the_login()
@app.route('/user/<username>/')
def profile(username): pass
with app.test_request_context():
print(url_for('index'), url_for('login'), url_for('login', next='next'), url_for('profile', username='John Doe'), sep='\n')
# 使用url_for的好处在于
# 反向构建通常比硬编码更具备描述性。更重要的是,它允许你一次性修改 URL, 而不是到处找 URL 修改。
# 构建 URL 能够显式地处理特殊字符和 Unicode 转义,因此你不必去处理这些。
# 如果你的应用不在 URL 根目录下(比如,在 /myapplication 而不在 /), url_for() 将会适当地替你处理好。
3. 静态文件
动态的 web 应用同样需要静态文件。CSS 和 JavaScript 文件通常来源于此。理想情况下, 你的 web 服务器已经配置好为它们服务,然而在开发过程中 Flask 能够做到。 只要在你的包中或模块旁边创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。给静态文件生成 URL ,使用特殊的 ‘static’ 端点名: url_for(‘static’, filename=‘style.css’)
4. 渲染模板
- 基本使用
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 模板的全部功能。详细信息查看官方的 Jinja2 Template Documentation http://jinja.pocoo.org/2/documentation/templates 。在模版中你也可以使用 request, session 和 g 对象,也能使用函数 get_flashed_messages() 。
- 模板继承 http://www.pythondoc.com/flask/patterns/templateinheritance.html#template-inheritance
- 例子
<!doctype html> <title>Hello from Flask</title> {% if name %} <h1>Hello {{ name }}!</h1> {% else %} <h1>Hello World!</h1> {% endif %}
- 自动转义默认开启,因此如果 name 包含 HTML,它将会自动转义。如果你信任一个变量,并且你知道它是安全的 (例如一个模块把 wiki 标记转换到 HTML ),你可以用 Markup 类或 |safe 过滤器在模板中标记它是安全的。下面是Markup 类如何工作的基本介绍:
from flask import Markup print(Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>') # Markup(u'<strong>Hello <blink>hacker</blink>!</strong>') print(Markup.escape('<blink>hacker</blink>')) # Markup(u'<blink>hacker</blink>') print(Markup('<em>Marked up</em> » HTML').striptags()) # u'Marked up \xbb HTML'
- 在版本0.5后,自动转义不再在所有模版中启用。模板中下列后缀的文件会触发自动转义:.html, .htm, .xml, .xhtml。从字符串加载的模板会禁用自动转义。
5. requset
- test_request_context 与 requst_context
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' with app.request_context(environ): assert request.method == 'POST'
- request.method/path/form/args/files/cookies
@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' return render_template('login.html', error=error) # 如果在 form 属性中不存在上述键值会发生些什么?在这种情况下会触发一个特别的 KeyError。 你可以像捕获标准的 KeyError 来捕获它,如果你不这样去做, # 会显示一个 HTTP 400 Bad Request 错误页面。 所以很多情况下你不需要处理这个问题。 # 可以用 args 属性来接收在 URL ( ?key=value ) 中提交的参数: search_word = request.args.get('key', 'default') # 我们推荐使用 get 来访问 URL 参数或捕获 KeyError ,因为用户可能会修改 URL, 向他们显示一个 400 bad request 页面不是用户友好的。
- 文件上传: 你能够很容易地用 Flask 处理文件上传。只要确保在你的 HTML 表单中不要忘记设置属性 enctype=“multipart/form-data”, 否则浏览器将不传送文件。
- 基本使用
# 上传的文件是存储在内存或者文件系统上一个临时位置。你可以通过请求对象中 files 属性访问这些文件。 每个上传的文件都会存储在这个属性字典里。 # 它表现得像一个标准的 Python file 对象,但是它同样具有 save() 方法,该方法允许你存储文件在服务器的文件系统上。 @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')
- 文件名
# 如果你想要知道在上传到你的应用之前在客户端的文件名称,你可以访问 filename 属性。但请记住永远不要信任这个值,因为这个值可以伪造。 # 如果你想要使用客户端的文件名来在服务器上存储文件, 把它传递到 Werkzeug 提供给你的 secure_filename() 函数: 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:
from flask import request from flask import make_response @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. resp = make_response(render_template(...)) resp.set_cookie('username', 'the username') return resp
6. 重定向和错误
- 用 redirect() 函数重定向用户到其它地方。能够用 abort() 函数提前中断一个请求并带有一个错误代码。
from flask import abort, redirect, url_for @app.route('/') def index(): return redirect(url_for('login')) @app.route('/login') def login(): abort(401) # 只是为了测试而已,实际写代码的时候不会这样 this_is_never_executed()
- 默认情况下,每个错误代码会显示一个黑白错误页面。如果你想定制错误页面,可以使用 errorhandler() 装饰器:
@app.errorhandler(404) def page_not_found(error): return render_template('page_not_found.html'), 404
7. response
- 一个视图函数(带有app.route/errorhandler等等的函数)的返回值会被自动转换为一个响应对象。如果返回值是一个字符串,它被转换成一个响应主体是该字符串,响应码为 200 OK ,媒体类型为 text/html 的响应对象。Flask 把返回值转换成响应对象的逻辑如下:
- 如果返回的是一个合法的响应对象,它会被从视图直接返回。
- 如果返回的是一个字符串,响应对象会用字符串数据和默认参数创建。
- 如果返回的是一个元组而且元组中元素能够提供额外的信息。这样的元组必须是 (response, status, headers) 形式且至少含有一个元素。 status 值将会覆盖状态代码,headers 可以是一个列表或额外的消息头值字典。
- 如果上述条件均不满足,Flask 会假设返回值是一个合法的 WSGI 应用程序,并转换为一个请求对象。
- 如果你想要获取在视图中得到的响应对象,你可以用函数 make_response() 。
@app.errorhandler(404) def not_found(error): resp = make_response(render_template('error.html'), 404) resp.headers['X-Something'] = 'A value' return resp
8. session
- 除了请求对象,还有第二个称为 session 对象允许你在不同请求间存储特定用户的信息。 这是在 cookies 的基础上实现的,并且在 cookies 中使用加密的签名。这意味着用户可以查看 cookie 的内容, 但是不能修改它,除非它知道签名的密钥。要使用会话,你需要设置一个密钥。这里介绍会话如何工作:
from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) @app.route('/') def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in' @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><input type=submit value=Login> </form>''' @app.route('/logout') def logout(): # remove the username from the session if it's there session.pop('username', None) return redirect(url_for('index')) # set the secret key. keep this really secret: app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' # 这里提到的 escape() 可以在你不使用模板引擎的时候做转义(如同本例)。
- 怎样产生一个好的密钥
import os os.urandom(24) # '\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8' 目标值
- 使用基于 cookie 的会话需注意: Flask 会将你放进会话对象的值序列化到 cookie。如果你试图寻找一个跨请求不能存留的值, cookies 确实是启用的,并且你不会获得明确的错误信息,检查你页面请求中 cookie 的大小,并与 web 浏览器所支持的大小对比。
9. 消息闪烁
- 好的应用和用户界面全部是关于反馈。如果用户得不到足够的反馈,他们可能会变得讨厌这个应用。Flask 提供了一个真正的简单的方式来通过消息闪现系统给用户反馈。消息闪现系统基本上使得在请求结束时记录信息并在下一个(且仅在下一个)请求中可以被访问。通常结合模板布局来显示消息。使用 flash() 方法来闪现一个消息,使用 get_flashed_messages() 能够获取消息, get_flashed_messages() 也能用于模版中。
- 消息闪现
10. 日志
- 版本0.3后出现,日志调用的例子:
app.logger.debug('A value for debugging') app.logger.warning('A warning occurred (%d apples)', 42) app.logger.error('An error occurred')
- 附带的 logger 是一个标准的日志类 Logger ,因此更多的信息请 查阅官方文档logging documentation。
11. 整合WSGI中间件
- 如果你想给你的应用添加 WSGI 中间件,你可以封装内部 WSGI 应用。例如如果你想使用 Werkzeug 包中的某个中间件来应付 lighttpd 中的 bugs,你可以这样做:
from werkzeug.contrib.fixers import LighttpdCGIRootFix app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
12. 部署到Web服务器
- 准备好部署你的新 Flask 应用?你可以立即部署到托管平台来完成快速入门,以下是向小项目提供免费的方案:
- 你可以托管 Flask 应用的其它选择:
- 如果你管理你自己的主机并且想要自己运行,请参看 部署方式。