Flask交互主要逻辑步骤:
1)用户在浏览器输入URL访问某个资源。
2)Flask接收用户请求并分析请求的URL。
3)为这个URL找到对应的处理函数。
4)执行函数并生成响应,返回给浏览器。
5)浏览器接收并解析响应,将信息显示在页面中
注意:当前py文件不是默认文件app.py,
需要使用赋值变量方式默认window命令 export FLASK_APP=hello
运行对方可见ip,即他人可以通过当前局域网访问该ip
执行命令 flask run --host=0.0.0.0
改变当前端口号:flask run --port=8000
flask_foo 扩展
from flask import Flask
from flask_foo import Foo
app = Flask(__name__)
foo = Foo(app)
# 添加键值对修改配置
app.config['ADMIN_NAME'] = 'Peter'
# 修改配置
app.config.update(
TESTING=True,
SECRET_KEY='_5#yF4Q8z\n\xec]/'
)
flask 命令
routes Show the routes for the app.
run Run a development server.
shell Run a shell in the app context.
状态码
200,请求被正常处理,
201 请求被处理,创建了一个新资源
204 请求处理成功,但无内容返回
301 永久重定向 302 临时性重定向
304 请求的资源未被修改,重定向到缓存的资源
400 表示请求无效,请求报文中存在错误401 请求的资源需要获取授权信息 403 请求的资源被服务器拒绝访问
404 服务器上无法找到请求的资源或URL无效500 服务器内部发生错误
cookie
Cookie指Web服务器为了存储某些数据(比如用户信息)而保存在
浏览器上的小型文本数据。浏览器会在一定时间内保存它,并在下一次
向同一个服务器发送请求时附带这些数据
session设置密钥
app.secret_key = 'secret string'
# 等价于
# 环境配置 set SECRET_KEY=secret string
import os app.secret_key = os.getenv('SECRET_KEY', 'secret string'
判断用户是否处于认证状态
from flask import request, session, Flask
app = Flask(__name__)
@app.route('/')
@app.route('/hello')
def hello():
name = request.args.get('name')
if name is None:
name = request.cookies.get('name', 'Human')
response = '<h1>Hello, %s!</h1>' % name
# 根据用户认证状态返回不同的内容
if 'logged_in' in session:
response += '[Authenticated]'
else:
response += '[Not Authenticated]'
return response
模拟管理后台
from flask import session, abort
@app.route('/admin')
def admin():
if 'logged_in' not in session:
abort(403)
return 'Welcome to admin page.'
登出用户,把登入的cookie删除
from flask import session
@app.route('/logout')
def logout():
if 'logged_in' in session:
session.pop('logged_in')
return redirect(url_for('hello'))
借助g我们可以将这个操作移动到before_request处理函数中执行
from flask import g # 相关变量名:current_app,requests,session
@app.before_request
def get_name():
g.name = request.args.get('name')
程序上下文对象使用app.app_context()获取
from flask import current_app
with app.app_context():
# 显式地使用push()方法推送(激活)上下文,在执行完相关
# 操作时使用pop()方法销毁上下文
# 请求上下文可以通过test_request_context()方法临时创建
with app.test_request_context('/hello'):
# ... request.method
session 模拟用户认证
@app.route('/login')
def login():
session['logged_in'] = True # 写入session
return redirect(url_for('hello'))
为视图创建多个URL
@app.route('/')
@app.route('/haha')
def hello_world():
name = request.args.get('name', 'Flask') # 获取查询参数name的值
return '<h1>Hello, %s!<h1>' % name
# @app.route('/hello', methods=['GET', 'POST']) # 同时获取get,post请求
# def hello():
# return '<h1>Hello, Flask!</h1>'
# @app.route('goback/<int:year>') # 转换器 string,float,int,path,
# def go_back(year):
# return '<p>Welcome to %d!</p>' % (2018 - year)
set_cookie方法设置
@app.route('/set/<name>')
def set_cookie(name):
response = make_response(redirect(url_for('hello')))
response.set_cookie('name', name)
return response
Cookie可以通过请求对象的cookies属性读取
@app.route('/')
@app.route('/hel')
def hel():
name = request.args.get('name')
if name is None:
name = request.cookies.get('name', 'Human') # 从Cookie中获取name值
return '<h1>Hello, %s</h1>' % name
any转换器
colors = ['blue', 'white', 'red']
@app.route('/colors/<any(%s):color>' % str(colors)[1:-1])
def pass():
pass
动态URL匹配
@app.route('/greet/<name>', defaults={'name': 'Programmer'})
def greet(name):
return '<h1>Hello, %s!</h1>' % name
redirect 重定向
@app.route('/he')
def he():
return redirect('http://www.example.com')
如果要在程序内重定向到其他视图,那么只需在redirect()函数中
使用url_for()函数生成目标URL
@app.route('/hi')
def hi():
return redirect(url_for('hello')) # 重定向到/hello
abort()函数中传入状态码即可返回对应的错误响应
@app.route('/404')
def not_found():
abort(404) # 一经调用,后续函数不再执行
使用其他MIME类型,使用make_response(),mimetype
@app.route('/foo')
def foo():
response = make_response('Hello, World!')
response.mimetype = 'text/plain'
# json格式设置
# data = {
# 'name': 'Grey Li',
# 'gender': 'male'
# }
# response = make_response(json.dumps(data)
# 上述json格式可等同于jsonify方法
# return jsonify(name='Grey Li', gender='male'
return response
请求钩子
@app.before_request
# eg:
# before_first_request,after_request,
# teardown_request(即使出现异常,在每个请求结束后运行),
# after_this_request(视图函数内注册一个函数,在这请求结束后运行)
def do_something():
pass # 这里的代码会在每个请求处理前执
使用它注册的回调函数会在程序上下文被销毁时调用,
而且通常也会在请求上下文被销毁时调用
# eg:你需要在每个请求处理结束后销毁数据库连接
# @app.teardown_appcontext
# def teardown_db(exception):
# db.close()
查询参数
@app.route('/foo')
def foo():
return '<h1>Foo page</h1><a href="%s">Do something and redirect</a>' % \
url_for('do_something', next=request.full_path)
# 使用request.full_path获取当前页面的完整路径
# 等价于
# return redirect(request.args.get('next')
# return redirect(request.args.get('next', url_for('hello'))
验证URL的安全性
from urlparse import urlparse, urljoin # Python3需要从urllib.parse导入
from flask import request
def is_safe_url(target):
ref_url = urlparse(request.host_url)
test_url = urlparse(urljoin(request.host_url, target))
return test_url.scheme in ('http', 'https') and \
ref_url.netloc == test_url.netloc
is_safe_url()验证next和referer的值
def redirect_back(default='hello', **kwargs):
for target in request.args.get('next'), request.referrer:
if not target:
continue
if is_safe_url(target):
# return redirect(target)
return redirect(url_for(default, **kwargs))
空值
@app.route('/post/delete/<int:post_id>', methods=['DELETE'])
def delete_post(post_id):
...
return '', 204
显示虚拟文章
# 文章的随机正文通过Jinja2提供的generate_lorem_ipsum()函数生成 默认n=5
# $.ajax()等同于jQuery.ajax()
# $(function(){...})函数,这个函数是常见的$(document).ready(function(){...})
from jinja2.utils import generate_lorem_ipsum
@app.route('/post')
def show_post():
post_body = generate_lorem_ipsum(n=2) # 生成两段随机文本
return '''
<h1>A very long post</h1>
<div class="body">%s</div>
<button id="load">Load More</button>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript">
$(function() {
$('#load').click(function() {
$.ajax({
url: '/more', // 目标URL
type: 'get', // 请求方法
success: function(data){ // 返回2XX响应后触发的回调函数
$('.body').append(data); // 将返回的响应插入到页面中
}
})
})
})
</script>''' % post_body
escape函数
from jinja2 import escape
@app.route('/hello')
def hello():
name = request.args.get('name')
response = '<h1>Hello, %s!</h1>' % escape(name)
常见应用
def redirect_back1(default='hello', **kwargs):
for target in request.args.get('next'), request.referrer:
if target:
# return redirect(target)
return redirect(url_for(default, **kwargs))
@app.route('/bar')
def bar():
return '<h1>Bar page</h1><a href="%s">Do something and redirect</a>' % \
url_for('do_something', next=request.full_path)