惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Application and Cybersecurity Blog
Application and Cybersecurity Blog
A
About on SuperTechFans
S
SegmentFault 最新的问题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Help Net Security
Help Net Security
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
O
OpenAI News
美团技术团队
月光博客
月光博客
Apple Machine Learning Research
Apple Machine Learning Research
Schneier on Security
Schneier on Security
Webroot Blog
Webroot Blog
Cyberwarzone
Cyberwarzone
Hacker News - Newest:
Hacker News - Newest: "LLM"
Google Online Security Blog
Google Online Security Blog
T
Tenable Blog
S
Security Affairs
博客园_首页
S
Schneier on Security
Security Latest
Security Latest
T
Threat Research - Cisco Blogs
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
Spread Privacy
Spread Privacy
量子位
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
K
Kaspersky official blog
Hugging Face - Blog
Hugging Face - Blog
TaoSecurity Blog
TaoSecurity Blog
博客园 - 聂微东
Vercel News
Vercel News
M
MIT News - Artificial intelligence
T
Troy Hunt's Blog
B
Blog
MongoDB | Blog
MongoDB | Blog
Martin Fowler
Martin Fowler
Attack and Defense Labs
Attack and Defense Labs
L
LINUX DO - 最新话题
D
DataBreaches.Net
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Stack Overflow Blog
Stack Overflow Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
博客园 - Franky
W
WeLiveSecurity
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
F
Fortinet All Blogs
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Check Point Blog
H
Hacker News: Front Page

Posts on WKLKEN THINKING

apisix 中的 lrucache apisix 中的服务发现机制 apisix 中的负载均衡 apisix etcd机制 聊聊框架 关于 k8s 的 zero downtime deployment 一些建议 apisix 遇到的一些问题 关于在除夕前一天换了一个洗衣机的故事 Django DRF 性能优化 DRF 的一些实践 Part1: Serializer DRF继承关系图 Better Code: 关于接口的灵活性 新的仓库: wklken/naming 缓存使用的一些经验 Better Code: 抽象: 可扩展性与可维护性的抉择 Better Code: 异常时, 该提示用户哪些信息? Better Code: 更好的异常日志打印 Go: some libs Go: go-redis/cache升级的坑 Go: logrus性能提升 Go: gin validation 远程办公的一点总结 Go: 开发过程中的一些bug 项目管理实践: 风险驱动开发 Go: 一种error wrap调用链处理方式 漫谈技术选型 Go: 基于 apitest 做handler层单元测试 Go: go-sql-driver interpolateparams参数优化 [分享]深度工作 你需要更多的思考时间 Django项目重构小结 工作七年小结: 学习,生活及其他 [分享]bash日常: bash-utils 极客时间推广海报 2017总结: 予时光以意义 k8s APIServer源码: api注册详细细节 k8s APIServer源码: api注册主体流程 k8s APIServer源码: 服务启动 k8s APIServer源码: go-restful框架 重构 - 读书笔记(Python示例) 写给新人的沟通建议 vim 杂谈 - 关于快速编辑 vim 杂谈 - 关于移动 读书笔记-重构: 章11 处理概括关系 读书笔记-重构: 章10 简化函数调用 读书笔记-重构: 章9 简化表达式 读书笔记-重构: 章8 重新组织数据 读书笔记-重构: 章7 在对象之间搬移特性 读书笔记-重构: 章6 重新组织函数 Python 代码规范小结 [分享]关于vim ElasticSearch集群部署文档 Logstash+ElasticSearch处理mysql慢查询日志 [分享]关于代码调试DE那些事 Logstash+ElasticSearch+Kibana- 实现相对通用的数据收集分析 ELK维护的一些点(二) [分享]Python源码剖析-数据结构 一些Centos Python生产环境的部署命令 摘录<<6个月学会任何一种外语>> ELK 维护的一些点 也许是一个新的开始 一些vim的个性化配置 读书笔记-调试九法 这段时间的一些想法 Python 源码阅读 - 垃圾回收机制 我为什么要写博客 APUE笔记-第一章 UNIX基础知识 Python源码阅读-闭包的实现 Python源码阅读-内存管理机制(二) Python源码阅读-内存管理机制(一) Python-基础-数据结构小结 '活动'设计的一些trick 一些简单的Python测试题 我的tmux配置及说明【k-tmux】 Review and Restart 工作四周年小结 vim插件: surround & repeat[成对符号编辑] vim插件: gundo[时光机] vim插件: expand-region[区域选中] vim插件: quickrun[快速执行] vim插件: trailing-whitespace[行尾空格处理] vim插件: closetag[成对标签补全] vim插件: ctrlp[文件搜索] vim插件: airline[状态栏增强] vim插件: theme[主题] vim插件: tagbar[大纲式导航] vim插件: nerdcommenter[快速注释] vim插件: rainbow_parentheses[括号高亮] vim插件: syntastic[语法检查] vim插件: delimitmate[符号自动补全] vim插件: matchit[成对标签跳转] vim插件: easy-align[快速对齐] vim插件: multiple-cursors[多光标操作] vim插件: vim-signature[快速标记跳转] vim插件: easymotion[快速跳转] vim插件: vundle[管理插件] Elasticsearch几个问题的解决 分享一份 Vim 简介PPT k-vim 更新9.0版本 关于知识管理工具的思考
Flask使用小结
2013-09-09 · via Posts on WKLKEN THINKING

flask

flask 使用的一些整理

资源

Flask 文档|英文| expore flask| 快速教材| flask-admin| Flask-DebugToolbar| Flask-Login| Flask-Cache| flask-sqlalchemy| flask-security| Flask-mako| Flask-Genshi| WTForms

Flask Extensions


最简单的hello world

#!/usr/bin/env python
# encoding: utf-8

from flask import Flask
app = Flask(__name__)

@app.route('/')
def index():
    return 'hello world'

if __name__ == '__main__':
    app.run(debug=True)
    #app.run(host='127.0.0.1', port=8000)

之后,访问http://localhost:5000

支持post/get提交

:::python
@app.route('/', methods=['GET', 'POST'])

多个url指向

:::python
@app.route('/')
@app.route('/index')

不管post/get使用统一的接收

:::python
from flask import request
args = request.args if request.method == 'GET' else request.form
a = args.get('a', 'default')

处理json请求

request的header中

"Content-Type": "application/json"

处理时:

data = request.get_json(silent=False)

获取post提交中的checkbox

{%for page in pages %}
<tr><td><input type=checkbox name=do_delete value="{{ page['id'] }}"></td><td>
{%endfor%}

page_ids = request.form.getlist("do_delete")

使用url中的参数

:::python
@app.route('/query/<qid>/')
def query(qid):
    pass

在request开始结束dosomething

一般可以处理数据库连接等等

:::python
from flask import g

app = .....

@app.before_request
def before_request():
    g.session = create_session()

@app.teardown_request
def teardown_request(exception):
    g.session.close()

注册Jinja2模板中使用的过滤器

:::python
@app.template_filter('reverse')
def reverse_filter(s):
    return s[::-1]

或者

:::python
def reverse_filter(s):
    return s[::-1]
app.jinja_env.filters['reverse'] = reverse_filter

可以这么用

:::python
def a():...
def b():...

FIL = {'a': a, 'b':b}
app.jinja_env.filters.update(FIL)

注册Jinja2模板中使用的全局变量

:::python
JINJA2_GLOBALS = {'MEDIA_PREFIX': '/media/'}
app.jinja_env.globals.update(JINJA2_GLOBALS)

定义应用使用的template和static目录

:::python
app = Flask(__name__, template_folder=settings.TEMPLATE_FOLDER, static_folder = settings.STATIC_PATH)

使用Blueprint

:::python
from flask import Blueprint
bp_test = Blueprint('test', __name__)
#bp_test = Blueprint('test', __name__, url_prefix='/abc')

@bp_test.route('/')

--------
from xxx import bp_test

app = Flask(__name__)
app.register_blueprint(bp_test)

实例:

bp_video = Blueprint('video', __name__, url_prefix='/kw_news/video')
@bp_video.route('/search/category/', methods=['POST', 'GET'])
#注意这种情况下Blueprint中url_prefix不能以 '/' 结尾, 否则404

使用session

包装cookie实现的,没有session id

:::python
app.secret_key = 'PS#yio`%_!((f_or(%)))s'

然后
from flask import session

session['somekey'] = 1
session.pop('logged_in', None)

session.clear()

#过期时间,通过cookie实现的
from datetime import timedelta
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)

反向路由

:::python
from flask import url_for, render_template

@app.route("/")
def home():
    login_uri = url_for("login", next=url_for("home"))
    return render_template("home.html", **locals())

上传文件

:::html
<form action="/image/upload/" method="post" enctype="multipart/form-data">
<input type="file" name="upload" />

接收

:::python
f = request.files.get('upload')
img_data = f.read()

直接返回某个文件

:::python
return send_file(settings.TEMPLATE_FOLDER + 'tweet/tweet_list.html')

请求重定向

文档

flask.redirect(location, code=302) the redirect status code. defaults to 302.Supported codes are 301, 302, 303, 305, and 307. 300 is not supported.

:::python
@app.route('/')
def hello():
    return redirect(url_for('foo'))

@app.route('/foo')
def foo():
    return'Hello Foo!'

获取用户真实ip

从request.headers获取

:::python
real_ip = request.headers.get('X-Real-Ip', request.remote_addr)

或者, 使用werkzeug的middleware 文档

from werkzeug.contrib.fixers import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

return json & jsonp

:::python
import json
from flask import jsonify, Response, json

data = [] # or others
return jsonify(ok=True, data=data)

jsonp_callback =  request.args.get('callback', '')
if jsonp_callback:
    return Response(
            "%s(%s);" % (jsonp_callback, json.dumps({'ok': True, 'data':data})),
            mimetype="text/javascript"
            )
return ok_jsonify(data)

配置读取方法

:::python
# create our little application :)
app = Flask(__name__)

# Load default config and override config from an environment variable
app.config.update(dict(
    DATABASE='/tmp/flaskr.db',
    DEBUG=True,
    SECRET_KEY='development key',
    USERNAME='admin',
    PASSWORD='default'
))
app.config.from_envvar('FLASKR_SETTINGS', silent=True)


------------------
# configuration
DATABASE = '/tmp/minitwit.db'
PER_PAGE = 30
DEBUG = True
SECRET_KEY = 'development key'

# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('MINITWIT_SETTINGS', silent=True)

几个不常用的方法

:::python
from flask import abort, flash

abort
if not session.get('logged_in'):
    abort(401)

flash
flash('New entry was successfully posted')

异步调用

想在flask的一个请求中处理异步, 除了使用消息系统, 可以用简单的线程处理

from threading import Thread

def async(f):
    def wrapper(*args, **kwargs):
        thr = Thread(target=f, args=args, kwargs=kwargs)
        thr.start()
    return wrapper

@async
def dosomething(call_args):
    print call_args


in a request handler, call `dosomething`

error handler

@app.errorhandler(404)
def not_found_error(error):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_error(error):
    db.session.rollback()
    return render_template('500.html'), 500

项目配置

1.直接

app.config['HOST']='xxx.a.com'
print app.config.get('HOST')

2.环境变量

export MyAppConfig=/path/to/settings.cfg
app.config.from_envvar('MyAppConfig')

3.对象

 class Config(object):
     DEBUG = False
     TESTING = False
     DATABASE_URI = 'sqlite://:memory:'

 class ProductionConfig(Config):
     DATABASE_URI = 'mysql://user@localhost/foo'

 app.config.from_object(ProductionConfig)
 print app.config.get('DATABASE_URI') # mysql://user@localhost/foo

4.文件

# default_config.py
HOST = 'localhost'
PORT = 5000
DEBUG = True

app.config.from_pyfile('default_config.py')

EG. 一个create_app方法

:::python
from flask import Flask, g

def create_app(debug=settings.DEBUG):
    app = Flask(__name__,
                template_folder=settings.TEMPLATE_FOLDER,
                static_folder=settings.STATIC_FOLDER)

    app.register_blueprint(bp_test)

    app.jinja_env.globals.update(JINJA2_GLOBALS)
    app.jinja_env.filters.update(JINJA2_FILTERS)

    app.secret_key = 'PO+_)(*&678OUIJKKO#%_!(((%)))'

    @app.before_request
    def before_request():
        g.xxx = ...    #do some thing

    @app.teardown_request
    def teardown_request(exception):
        g.xxx = ...    #do some thing

    return app

app = create_app(settings.DEBUG)
host=settings.SERVER_IP
port=settings.SERVER_PORT
app.run(host=host, port=port)

change log:

2013-09-09 create
2014-10-25 update

wklken

2013-09-09