# 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 命令
# Commands:
# 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指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
from flask import Flask, request, redirect, url_for, abort, make_response, json, session
app = Flask(__name__)
# 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():
return '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 pas():
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
@app.route('/hello')
def hello():
pass
# 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 # 这里的代码会在每个请求处理前执
if __name__ == '__main__':
app.run()
# 后续
from flask import Flask, url_for, request, redirect
app = Flask(__name__)
# 使用它注册的回调函数会在程序上下文被销毁时调用,
# 而且通常也会在请求上下文被销毁时调用
# 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</a>' % url_for('do_something')
# @app.route('/bar')
# def bar():
# return '<h1>Bar page</h1><a href="%s">Do something </a>' % url_for('do_something')
#
@app.route('/do_something')
def do_something():
# do something
return redirect(url_for('hello'))
# 查询参数
@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)
if __name__ == '__main__':
app.run()
代码摘抄之Flask Web开发实战