读 Flask:Blueprint 的大致实现

Flask 的 Blueprint 本质上是一个记录了一系列动作的类, 当 flask app 执行 app.register_blueprint 的时候把这些动作一股脑的全部倒入到 app 这个容器中去.
其大致的执行顺序是:

  1. app = Flask(__name__)
  2. bp = Blueprint('blueprint', __name__)
  3. bp.before_request' \ 'bp.route' \ 'bp.errorhandler
  4. app.register_blueprint

Read More

读 Python: functools.wraps 做了什么

Python 标准库 functools 里面的 wraps 装饰器经常用于写装饰器,之前只知道它可以用来保留被装饰函数的元数据,但具体实现的方式和究竟保留了哪些数据都不清楚。最近看 Flask 源码时读到一行代码 return self.record(update_wrapper(wrapper, func))。 稍微看了一下原来 @wraps(func) 其实就是调用了 update_wrapper 这个函数,于是索性看个明白。

Read More

Flask-Admin 快速实现用户权限限制

这个办法基于以下两个事实:

  1. Flask Admin 本身是一个 Flask 蓝图
  2. Flask 的 ModelView 类可以通过 can_delete = True/False 等来关闭/开启相应的操作
    所以实现的办法是,给 Flask-Admin 蓝图的 before_request_funcs 注册一个 check_user_permission 函数,在每次请求之前根据用户的权限来刷新 ModelView 的设置。
    而蓝图的 before_request 必须要在 app.register_blueprint 调用之前,根据 Flask-Admin 创建蓝图和注册蓝图的流程来看,复写 ModelView 的 create_blueprint 这个函数就可以了。

Read More

读Flask: 一次完整的Request和Response周期

Flask只是一个python web框架,框架和server之间的数据交流,都是基于PEP3333所规范的WSGI, server调用framwork的某个callable进行数据交流。 这个callable, 可以是定义了__call__方法的类,或者任何函数等。
而Flask应用的数据入口和出口(callable)就是Flask类实例的wsgi_app函数。

1
2
3
4
5
6
7
8
def wsgi_app(self, environ, start_response):
with self.request_context(environ):
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()
response = self.make_response(rv)
response = self.process_response(response)
return response(environ, start_response)

wsgi_app接受从server发过来的environ环境变量,并且根据这个变量创建一个request context,然后在这个context下进行数据处理,最后返回数据到server。

Read More

读Flask:before(after)_request

Flask中可以使用@before_request等装饰器来注册一些函数,这些函数会在view_func之前被执行,通常可以用来做数据库初始化等操作。

1
2
3
4
5
6
7
8
9
10
def before_request(self, f):
"""Registers a function to run before each request."""
self.before_request_funcs.append(f)
return f

def preprocess_request(self):
for func in self.before_request_funcs:
rv = func()
if rv is not None:
return rv

Read More