开始决定认真的在网上写一些东西,主要缘由仍是在于但愿能提高学习效果。虽然说python写了有几年,可是web后端框架的确没怎么接触过,买了本狗书寥寥草草的过了一遍,发现不少东西仍是理解不深,真的是好记性不如烂笔头,知识也要从基础开始,退回来好好看看官方文档,再去看狗书吧。
网上有翻译好的官方文档,基本是基于0.10.1版本翻译的,和目前版本对比了一下,细节上仍是有一些不一样(狗书也存在这个问题),因此仍是老老实实的看英文原版学习吧,目前的版本是0.12.2html
众所周知,flask是一个使用Python开发的“微型”Web框架,文档中特地强调了,所谓“微型”并不意味着Web应用的开发只能写在一个Python文件里,也不意味着flask自身功能不够丰富。“微型”的目的在于,保持一个“简单”而且“可扩展”的框架核心,为开发者提供一个选择自由的Web框架。基于此,开发者能够自由的选择数据库或模板引擎,为本身的Web应用作合适的选择。python
经过flask实现一个Hello World只须要几行代码linux
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello, World!'
把一头大象放进冰箱只需三步:web
这个示例代码与0.10版不一样,在旧版文档中,经过在代码中添加app.run()方法来运行这个Web应用,而在0.12版文档中,应用的启动工做使用了命令行的方式来处理:数据库
$ export FLASK_APP=hello.py $ flask run * Running on http://127.0.0.1:5000/
或者:flask
$ export FLASK_APP=hello.py $ python -m flask run * Running on http://127.0.0.1:5000/
经过给FLASK_APP环境变量赋值,告诉flask它的web应用是哪一个。我尝试了在代码中使用app.run()方法启动,也同样能够执行。后端
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run('0.0.0.0')
开启debug模式可实现代码变动的热加载,即:代码修改后,不须要重启flask server,就能够自动触发变动代码的载入。
另外,开启debug模式能够实如今页面查看运行中的错误信息,追踪错误发生缘由,适合开发过程当中的错误调试。
开启Debug模式的方法包括:浏览器
$ export FLASK_DEBUG=1 $ flask run
以及在代码中,为Flask类实例的run方法中,指明debug参数为True:安全
app.run(debug=True)
在Flask下,用户可使用@app.route()装饰器为页面设计具备可读性的静态路由,也能够在路由部分中加入变量,以使路由动态可变。
路由的形式相似于linux下的文件路径。
示例以下:cookie
#静态路由 @app.route('/hello') def hello(): return 'Hello, World' #使用动态变量的路由(未指定变量类型) @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
指定的路由变量,能够做为被装饰的函数参数传入进来。当路由尾部加入'/'时,不管在浏览器地址栏中输入的网址尾部是否加'/',浏览器都会自动重定向到有/的路由上。
flask模块提供了url_for()函数用于获取函数的URL,所以在项目中全部引用到URL字符串的地方,均可以使用url_for(func, **kwargs)来获取函数的URL,这样作的好处在于,可使项目更容易维护。当某函数URL发生变动时,只需修改一处地方便可,而无须修改每一处URL引用。我的认为,在开发过程的任什么时候候,使用硬编码都是极为不妥的。
http做为客户端与服务端的交互协议,包含了不一样类型的请求方法(method),Flask中,最长使用的是GET、PUT和POST方法,一条路由适用哪一种方法,能够在route装饰器中定义。如不明肯定义,route装饰器中默认定义为GET方法。
官方例子:
from flask import request @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': do_the_login() else: show_the_login_form()
http还包括HEAD以及OPTIONS方法,在较新的Flask中,已经为用户内部实现,所以通常开发过程当中无需在乎。
Flask的静态文件目录默认为项目目录内的static目录,通常全部静态文件都存放在这个目录内。
Flask内置了Jinja2做为模板引擎,并提供render_template方法用于模板渲染,使用起来很方便,只需在方法内指定须要渲染的html文件名称,并传入模板变量值便可实现模板渲染。
官方示例:
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目录内寻找模板文件。
官方模板文件示例:
<!doctype html> <title>Hello from Flask</title> {% if name %} <h1>Hello {{ name }}!</h1> {% else %} <h1>Hello, World!</h1> {% endif %}
模板文件之间可实现继承,这一特性保证了不一样页面内的重复页面元素(页头、页脚、导航栏)等,可经过模板继承的方式迅速实现。
来自客户端的http请求,在server端以request对象存在。
Flask为每个request建立一个处理线程,并在线程内部建立上下文实现线程安全。所以开发者在开发过程当中不须要为线程安全费太多心思。
关于request对象,获取客户端传输来的数据方式很是简单,相似于字典的形式,只须要在request.method中指明key的值便可实现:
#获取登陆表单数据 @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)
文档在此处还说起了文件上传场景以及cookie的简单用法,后续文档应当有更加详细的记录,在此不详述。
Flask使用redirect()函数处理重定向逻辑。使用abort(error_code)处理错误返回。
若但愿对错误页面进行定制,可以使用errorhandler(error_code)装饰器修饰对应的视图函数,定义本地错误页面。
flask有本身的应答处理逻辑,可大体总结为:
1.视图函数返回字符串时,flask会自动将返回字符串封装如标准response对象内
2.用户也能够在视图函数内使用make_response()函数建立response对象并返回,这样作的意义是,在返回前用户能够对response对象的部份内容进行设置,例如cookie。
3.若是返回对象是一个tuple,那么内容顺序格式应知足(response, status, headers)这样的格式
session记录了客户端与server之间的一些信息,官方文档给出了用户登录状态的例子。经过判断session中是否存在username键值来判断用户是否已登陆,以此为依据返回不一样的展现内容。
示例以下:
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 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'
使用session的前提是必须设置密钥,密钥的获取可使用python提供的随机函数生成。
>>> import os >>> os.urandom(24)
flask的日志模块与python的logging模块使用方式相似,应该是作了内部集成,代码形式略微不一样,在此作记录:
app.logger.debug('A value for debugging') app.logger.warning('A warning occurred (%d apples)', 42) app.logger.error('An error occurred')