`

(转载)Flask 出坑记

阅读更多

Flask 是个 Python Web 框架. 网站上文档例子都很详尽, 这里就不废话了, 只是来扯两个使用中需要注意的地方.
装饰器对被装饰函数的名字是敏感的

    首先是应用程序装饰器, 如官网上的例子

1
2
3
4
5
6
7
8
import flask
app = flask.Flask(__name__)
 
@app.route('/')
def hello():
    return 'Hello World'
 
if __name__ == '__main__': app.run(port=7777)


    这个装饰器挂在哪个函数上, 哪个函数就成为一个处理函数. 这个特性让那些看多了 django 或者 tornado 起手先一大堆类定义的人一下子全高潮了, 大呼简单函数拯救世界. 不过这东西有时候相当坑. 先来看一个熊孩子特性, 把上面代码改成这样

1
2
3
4
5
6
import flask
app = flask.Flask(__name__)
 
app.route('/')(lambda: 'Hello World')
 
if __name__ == '__main__': app.run(port=7777)


    然后试着 curl 一下 http://localhost:7777, 没问题, 还是返回 'Hello World'. 好, 加一句

1
2
3
4
5
6
7
import flask
app = flask.Flask(__name__)
 
app.route('/')(lambda: 'Hello World')
app.route('/wtf')(lambda: 'I bought a watch last year')
 
if __name__ == '__main__': app.run(port=7777)


    再来一发

1
2
3
4
$ curl http://localhost:7777/
I bought a watch last year
$ curl http://localhost:7777/wtf
I bought a watch last year


    怎么都是「I bought a watch last year」?! 我去年买了个表!
    查了一通文档才发现 Flask 会索引被装饰函数的名字, 并根据这些名字来派发请求. 好了, 结论是不要在 Flask 里玩 lambda, 因为 Python 里面所有 lambda 名字都一个样

1
2
3
4
5
6
>>> x = lambda : None
>>> x.__name__
'<lambda>'
>>> y = lambda m, n: m + n
>>> y.__name__
'<lambda>'


    傲娇程序员的第一反应可能是「才不会到处用 lambda 只是偶尔写一个换换口味」. 且慢, 倒不是说 lambda 有问题, 而是下面这种用况会出事

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import flask
 
app = flask.Flask(__name__)
 
def handler_logger(f):
    def g(*args, **kwargs):
        print 'before request'
        r = f(*args, **kwargs)
        print 'after request'
        return r
    return g
 
@app.route('/')
@handler_logger
def root():
    return 'Hello World'
 
@app.route('/wtf')
@handler_logger
def wtf():
    return 'I bought a watch last year'
 
if __name__ == '__main__': app.run(port=7777)


    同样的结果, 访问两个 URL 看到的都是后一个函数的结果.
    刚才已经说了 Flask 对被包装函数的名字是敏感的, 所以解决上述问题的方法便是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import flask
import functools
 
app = flask.Flask(__name__)
 
def handler_logger(f):
    @functools.wraps(f)
    def g(*args, **kwargs):
        print 'before request'
        r = f(*args, **kwargs)
        print 'after request'
        return r
    return g
 
@app.route('/')
@handler_logger
def root():
    return 'Hello World'
 
@app.route('/wtf')
@handler_logger
def wtf():
    return 'I bought a watch last year'
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()


获取 POST 请求体

    21 世纪的 Web 交互中服务器跟浏览器互相丢 JSON 已经成了司空见惯的事情. 服务器上要搞到 JSON 数据当然是直接访问 POST 请求体了, 如

1
2
3
4
5
6
7
8
9
10
11
12
13
import flask
import functools
 
app = flask.Flask(__name__)
 
@app.route('/wtf', methods=['POST'])
def wtf():
    return 'Received: ' + flask.request.data
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()


    按文档的说法, flask.request.data 包含请求数据字符串. 但其实这也是个坑, 默认情况下根本取不到请求数据

1
$ curl -d "[1,1,2,3,5,8]" http://localhost:7777/wtf


Received:
    熊孩子你把拿到的字符串给吃了吧? 实际上如果去看看那文档会看到并不如上面所说的那样, 而是
Contains the incoming request data as string in case it came with a mimetype Flask does not handle.
    后面这个状语从句真是着急, 那到底什么 mimetype 会使得 Flask does not handle 呢? 根本没说清楚啊. 扫一眼文档后面, 还有个东西可以用: flask.request.json, 但这货一般是 None, 只有当请求 mimetype 被设置为 application/json 的时候才有用, Flask 你真心是跟 mimetype 过不去啊. 也就是说得这样发请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import json
import flask
import functools
 
app = flask.Flask(__name__)
 
@app.route('/wtf', methods=['POST'])
def wtf():
    return 'Received: ' + json.dumps(flask.request.json)
 
def main():
    app.run(port=7777)
 
if __name__ == '__main__': main()

 

1
2
3
4
$ curl -d "[1,1,2,3,5,8]" localhost:7777/wtf
Received: null
$ curl -d "[1,1,2,3,5,8]" -H "Content-Type:application/json" localhost:7777/wtf
Received: [1, 1, 2, 3, 5, 8]


    问题是现在前端攻城狮都被浏览器兼容性折腾得满世界买表, 哪还有心情检查每个请求的 content-type 对不对. 况且这还只对 JSON 有效, 如果是山寨协议又怂了.
    好吧, 如果实在不行, 就挖到 WSGI 里面去好了, 比如这样

1
2
3
4
5
def request_data():
    d = flask.request.data
    if not d:
        return ''.join(flask.request.environ['wsgi.input'].readlines())
    return d


    这样 (在特定的 WSGI 环境中, 比如配合 gevent 使用时) 能获取请求数据 (这不还是坑么). 或者看看这个万能的方法. 好了, 请求字符串快到碗里来!

分享到:
评论

相关推荐

    基于flask的数据库管理系统

    开发语言Python 依赖项faker、flask、flask-sqlalchemy 适用于毕业设计、课后大作业、二次开发等 可查看数据库中的数据、修改、删除 可进一步拓展为图书管理系统等类似管理系统

    Flask简单代码

    Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask简单整理Flask...

    基于Flask的课堂扫脸考勤签到系统

    基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的课堂扫脸考勤签到系统基于Flask的...

    flask及依赖项安装文件

    flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖项安装文件flask及依赖...

    基于Flask和JQuery,实现表格管理平台(python)

    基于Flask框架,搭建一套简单的表格管理平台;本人已编写输出了”基于Flask和JQuery,实现表格管理平台“的相关博客,也可直接通过博客来了解。 https://mp.csdn.net/postedit/101231870

    flask

    flask库本身

    Flask_Web全栈开发阶段-flask框架.zip

    Flask_Web全栈开发阶段-flask框架.zip

    flask 安装

    Python +FLask 环境搭建

    python+flask微信小程序订餐系统源码.zip

    python+flask微信小程序订餐系统源码 python+flask微信小程序订餐系统源码python+flask微信小程序订餐系统源码 python+flask微信小程序订餐系统源码python+flask微信小程序订餐系统源码 ...

    Flask精美完整博客源码,含管理后台及个人中心,简单权限管理!

    Flask精美完整博客源码,含管理后台及个人中心,简单权限管理! 在终端运行如下几个命令创建虚拟环境并安装依赖,步骤是: 创建虚拟环境:python3 -m venv venv 激活虚拟环境:source venv/bin/activate 安转...

    记录一次关于python-flask蓝图的坑

    记录一次关于python-flask蓝图的坑一.简介二.特色三.flask规模化四. flask Blueprint 一.简介 Flask是一个使用Python编写的轻量级Web应用框架。基于Werkzeug WSGI工具箱和Jinja2 模板引擎。Flask使用BSD授权。Flask...

    python-flask-microservice_Flask框架_flask_phyton_

    python flask easyui 整合的快速web开发框架

    Flask+Web开发实战,flaskweb开发实战pdf,Python

    Flask+Web开发实战的PDF版本。Flask是目前最流行的Python Web框架之一。自2010年开源以来,Flask受到了越来越多的Python开发者的喜欢,其受欢迎程度不输于Django。

    flask蓝图模板生成

    自动创建flask应用模板的脚本,双击即可在当前目录创建一个flask应用框架并开始运行。

    flask form表单flask form表单forms.py

    flask form表单

    python2.7 flask离线安装

    python2.7 flask离线安装

    Flask课件.rar

    flask基础学习,Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。 Flask也被称为 “microframework” ,因为它使用简单的核心,用...

    Flask Web Development.pdf 最新 原版

    Take full creative control of your web applications with Flask, the Python-based microframework. With this hands-on book, you'll learn Flask from the ground up by developing a complete social blogging...

    flask 使用 flask_apscheduler 做定时循环任务的实现

    主要介绍了flask 使用 flask_apscheduler 做定时循环任务的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Global site tag (gtag.js) - Google Analytics