Flask
简单示例
from flask import Flask
#创建Flash实例,用于运行
app = Flask(__name__)
#给指定方法指定访问url
@app.route('/')
def hello():
return 'Hello World!'
if __name__ == '__main__':
app.run()
#默认app.run()在debug模式只限于你本地访问,如果想让外网可以访问,使用app.run(host='0.0.0.0')
Debug模式
默认生产模式下代码改动不会导致服务器重启以读取你的代码,在debug模式下代码改动会导致服务器重启并且会在错误时为你提供更多的信息,方便你调试.
#开启debug模式
app.debug = True
app.run()
#或者
app.run(debug=True)
路由
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
变量规则
指定通过url传入的值,也可以提前定好类型
| 类型 | 含义 |
|---|---|
| int | 整型 |
| float | 浮点型 |
| path | 像默认的一样,但是接受/ |
flask会自动帮你分析变量,匹配正确的类型的路由方法
@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
唯一的URL和重定向行为
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
尽管以上两个路由看起来相同,但是它们确实不同,一个在尾部有/,一个没有.
对于第一种情况,如果在访问时在projects后没有添加/,则Flask会帮你重定向到带/的URL
对于第二种情况,如果添加了/则会导致404错误.
URL创建
url_for()可以为指定的函数生成访问url.
第一个参数为函数名,第二个参数为关键字参数,对于传入的关键字参数,如果名称符合该函数路由声明的类型,则对应匹配.否则按照URL的查询参数构造URL
>>> from flask import Flask, url_for
>>> app = Flask(__name__)
>>> @app.route('/')
... def index(): pass
...
>>> @app.route('/login')
... def login(): pass
...
>>> @app.route('/user/<username>')
... def profile(username): pass
...
>>> with app.test_request_context():
... print url_for('index')
... print url_for('login')
... print url_for('login', next='/')
... print url_for('profile', username='John Doe')
...
/
/login
/login?next=/
/user/John%20Doe
with app.test_request_context()
意思是以服务器环境运行下列代码
Http 方法
默认route()定义的只接受GET请求,通过给route()制定methods参数可以改变可接受的Http方法请求
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()
静态文件
在你的package或者与你的module相邻的地方创建static文件夹,静态文件就可以通过/static被访问了.
生成static URLs
url_for('static', filename='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)
简单的Jinja2模板
<!doctype html>
<title>Hello from Flask</title>
{% if name %}
<h1>Hello {{ name }}!</h1>
{% else %}
<h1>Hello World!</h1>
{% endif %}
默认传入的参数会被进行转义以保证安全,如果确定安全或者有特殊情况需要不进行转义,使用Markup类.
>>> from flask import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup(u'<strong>Hello <blink>hacker</blink>!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup(u'<blink>hacker</blink>')
>>> Markup('<em>Marked up</em> » HTML').striptags()
u'Marked up \xbb HTML'
Changed in version 0.5: Autoescaping is no longer enabled for all templates. The following extensions for templates trigger autoescaping: .html, .htm, .xml, .xhtml. Templates loaded from a string will have autoescaping disabled.
访问请求数据
请求对象
from flask import request
通过request对象的method和form属性访问请求方法和请求参数
@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)
访问URL中的请求参数,使用args属性
searchword = request.args.get('key', '')
文件上传
flask自动帮你处理上传的文件,保存在内存中或者某个文件系统中,你可以通过files属性来访问,并且调用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')
...
可以通过file的filename属性获取文件名,但是该名称可能是伪造的,所以不要相信,在使用前调用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字典.如果你想要使用sessions,不要直接使用cookies,而是用Flask的Sessions类来安全的使用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.
写
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp
一般情况下,返回的都是字符串,Flask自动处理封装成response对象,但是在设置cookies时需要使用响应对象,所以这时就需要自己创建响应对象,然后对响应对象进行修改.
重定向和错误
使用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()装饰器定制错误页面
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
关于响应
响应的逻辑
1. 如果返回的是响应对象,那么直接返回该对象
2. 如果返回的是string,那么会通过string和默认的参数创建响应对象返回
3. 如果返回的是tuple,必须是(response,status,headers)的形式.status会复写状态码,headers可以提供额外的头信息.
4. 如果返回的都不是上面的,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
Sessions
使用Sessions需要指定 secret key,以下为简单的例子
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()函数帮你转义
如何生成好的secret Keys:
>>> import os
>>> os.urandom(24)
'\xfd{H\xe5<\x95\xf9\xe3\x96.5\xd1\x01O<!\xd5\xa2\xa0\x9fR"\xa1\xa8'
Message Flashing
Good applications and user interfaces are all about feedback. If the user does not get enough feedback they will probably end up hating the application. Flask provides a really simple way to give feedback to a user with the flashing system. The flashing system basically makes it possible to record a message at the end of a request and access it on the next (and only the next) request. This is usually combined with a layout template to expose the message.
To flash a message use the flash() method, to get hold of the messages you can use get_flashed_messages() which is also available in the templates. Check out the Message Flashing for a full example.
日志
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
使用的logger是标准的python Logger类,所以想了解更多信息去看logging文档
使用WSGI中间件
用中间件包装你的内部WSGI应用即可,
例:使用Werkzeug的中间件来处理lighttpd的bug
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
部署到Web服务器
http://flask.pocoo.org/docs/0.10/quickstart/#hooking-in-wsgi-middlewares
见页底
@(马克飞象)
Flask框架入门与实践
1082

被折叠的 条评论
为什么被折叠?



