导入Flask类,该类实例化对象是WSGI应用,第一个参数是应用模块名称,若单一模块,第一个参数应为__name__,
使用装饰器route()告诉Flask触发哪个URL,加入if __name__ == '__main__':确保服务器只会在该脚本被Python解释器
直接执行的时候才会运行,ctrl+c停止服务器
外部可见服务器:
运行服务器,只能在自己计算机上访问,网络其他地方不能访问,如果关闭debug,你可以让你的服务器对外可用,只要简单地改变
方法run()的调用:app.run(host='0.0.0.0'),操作系统监听所有公开的IP.
调试模式:
两种模式开启调试模式:app.debug = True或者作为run的一个参数传入:app.run(debug=True)
路由:
router()装饰器是用于把一个函数绑定到一个URL上,
@app.route('/')
def index():
return 'hehe'
变量规则:
为了给URL增加变量的部分,你需要把一些特定的字段标记成<username>,这些特定的字段将作为参数传入到你的函数中,也可以指定一个可选的转换器通过规则<converter:variable_name>
@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
int接受整数,float:同int一样,接受浮点数,path:和默认相似,也接受斜线
构建URL
可以使用url_for()来针对一个特定的函数构建一个URL,接受函数名作为第一参数,以及一些关键字参数,每个关键字参数对应URL规则的变量部分,未知变量部分被插入到URL中作为查询参数
@app.route('/user/<username>')
def profile(username):pass
url_for('profile',username='John Doe')
反向构建通常比硬编码更具有描述性,构建URL能够URL能够显式的处理特殊字符和Unicode转义,如果应用不在URL根目录下,url_for()适合处理
HTTP方法:
HTTP有不同的访问方法来访问urls,默认情况下,路由只会响应GET请求,但是能够通过给route()装饰器提供methods参数来改变,
@app.route('/login',methods=['GET','POST'])
如果使用GET方法,HEAD方法将会自动添加进来,OPTIONS能自动处理,
GET浏览器通知服务器只获取页面上的信息并且发送回来,
HEAD浏览器告诉服务器获取信息,但是只对头信息感兴趣,不需要整个页面的内容,在flask中不需要处理
POST:浏览器通知服务器要在URL上提交一些信息,服务器必须保证数据被存储且只存储一次,这是HTML表单通常发送数据到服务器的方法
PUT:同POST类似,但是服务器可能触发了多次存储过程,多次覆盖掉旧值,考虑到传输过程中连接丢失,这种情况下浏览器和服务器之间的系统可能安全的第二次接受请求
DELEtE:移除给定位置的信息
OPTIONS:给客户端体用一个快速的途径来指出这个URL支持哪些HTTP方法,自动实现
静态文件:
动态的web应用同样需要静态文件,只要在你的包中或模块旁边创建一个名为static的文件夹,在应用中使用/static即可访问
给静态文件生成URL,使用特殊的'static'端点名:url_for('static',filename='style.css')
这个文件应该存储在文件系统上称为static/style.css
渲染模板:
flask使用Jinjia2模板,可以使用方法render_template()来渲染模板,提供模板名称以及想要作为关键字参数传入模板的变量
from flask import render_template
@app.route('/hello/<name>')
def helllo(name = None):
return render_template(hello.html',name=name)
Flask将会在templates文件夹中寻找模板,
在模板中可以使用request,session也能使用函数
自动转义是开启,因此如果变量包含HTML将会自动转义,如果信任一个变量,并且知道他是安全的,可以使用Markup类,或|safe过滤器在模板中标记它是安全的自动转义不再在所有模版中启用。模板中下列后缀的文件会触发自动转义:.html
, .htm
, .xml
, .xhtml
。从字符串加载的模板会禁用自动转义。
接收请求数据:
在flask中全局对象request来提供这些信息,request是全局变量,为保证线程安全使用了上下文作用域
局部上下文:
Flask中的某些对象是全局对象,这些对象实际上是给定上下文的局部对象的代理,线程处理的上下文:一个请求传入,web服务器决定产生一个新线程(底层对象比线程更有能力处理并发系统),当flask开始它内部请求处理,它认定当前线程是活动的上下文并绑定当前的应用和WSGI环境到那个上下文(线程),以一种智能的方式实现,以至一个应用可以调用另一个应用而不会中断
针对单元测试最早的解决方案使用test_request_context()上下文管理器,结合with声明,将绑定一个测试请求来进行交互
from flask import request
with app.text_request_context('/hello',method="POST"):
assert request.path == '?hello'
assert request.method == 'POST'
另一个可能性就是传入整个WSGI环境到request_context()方法:
from flask import request
with app.request_context(environ):
assert request.method == 'POST'
请求对象
可以使用form属性来访问表单数据(数据在POST或者PUT中传输)
可以使用args属性来接收在URL(?key=value)中提交的参数:
search = request.args.get('key','')
文件上传
你可以很容易的使用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['file']
f.save('/var/www/uploads/upload_file.txt')
想要知道上传到你的应用之前在客户端的文件名称,可以访问filename属性,这个值可以伪造,想要使用客户端的文件名来在服务器上存储文件,把它传递到Werkzeug提供的secure_filename()函数:secure_filename(f.filename)
Cookies:
你可以使用cookies属性来访问cookies,用响应对象set_cookie来设置cookies.请求对象中的cookies属性是一个客户端发送所有的cookies的字典,如果要使用会话sesions,请不要直接使用cookies相反用Flask中的会话,Flask已经在cookies上增加了一些安全细节.
读取cookies:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
存储cookies:
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.setcookie('username','the username')
return resp
注意cookies是在响应对象中被设置,由于通常只是从视图函数返回字符串,Flask会将其转换为响应对象,如果显示的做,可以使用make_response()函数接着修改它,有时候可能要在响应对象不存在的地方设置cookie,利用延迟请求回调模式使得这种情况成为可能.
重定向和错误:
使用redirect()函数重定向用户到其他地方,能够用abort()函数提前中断一个请求并带有一个错误代码.
from flask import abort,redirect,url_for
@app.route('/login)
def index():
return redirect(url_for('login'))
@app.route('/')
def login():
abort(401)
this_is_never_executed()
这是一个相当无意义的例子,因为用户会从主页重定向到一个不能访问的页面,默认情况下,每个错误代码会显示一个黑白错误页面,如果想定制错误页面,可以使用errorhandler()装饰器
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'),404
404是在render_template()调用之后,告诉Flask该页的错误代码是404,即没有找到,默认的200被假定为一切正常
关于响应:
一个视图函数的返回值会被自动转换为一个响应对象,如果返回值是字符串,他被转换成一个响应主体是该字符串,错误代码为200,ok,媒体类型为text/html的响应对象.Flask把返回值转换成响应对象的逻辑如下:
1.如果返回的是一个合法的响应对象,他会从视图直接返回
2.如果返回的是一个字符串,响应对象会用字符串数据和默认参数创建
3.如果返回的是一个元组而且元组中元素能够提供额外的信息,这样的元组必须是(response,status,headers)形式且至少含有一个元素.status值将会覆盖状态代码,headers可以是一个列表或额外的消息头字典
4.如果上诉条件均不满足,Flask会假设返回值是一个合法的WSGI应用程序,并转换为一个请求对象
如果想获取在视图中得到的响应对象,可以用函数make_response()
@app.erroehandler(404)
def not_found(error):
resp = render_template('error.html'),404
@app.errorhandler(404)
def not_found(error):
resp = make_response(render_template('error.html'),404)
resp.headers['X-Something'] = 'A value'
return resp
会话
除了请求对象,还有第二个称为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['suername'])
return 'You are not logged in'
这里的escape()可以在你不是用模板引擎的时候转义
操作系统可以基于一个密码生成器来生成漂亮的随机值
import os
os.urandom(24)
使用基于cookie的会话需注意,Flask会将你放在会话对象的值序列化到cookie,如果你试图寻找一个夸请求不能存留的值,cookies确实是启用的,并且你不会获得明确的错误信息,检查你页面中cookie的大小,并与web浏览器所支持的大小对比
消息闪烁
好的应用和用户界面全部是基于反馈,Flask提供了一个真正的简单地方式来通过消息闪现系统给用户反馈,消息闪现系统基本上使得在请求结束时记录信息并在下一个(且仅在下一个)请求中访问.通常结合模板布局来显示信息
使用flash()方法来闪现一个消息,使用get_flashed_messages()能够获取消息,get_flashed_messages()也能用于模板中
日志:
app.logger.debug('A value for debugging')
app.logger.waring('A waring occurred ')
app.loger.error('An error occurred'')
整合wsgi中间件
给应用添加中间件,可以封装内部WSGI应用,如果想要使用Werkzeug包中的某个中间件来应付lighttpd中的bugs
from werkzeug.contrib.fixers import LighttpdCGIrOOTfIX
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)