如何在基于 class 的视图中使用 flask 路由?
How use flask route with class based view?
Django 风格Class 基于视图的很酷很强大的功能。但是 Flask 风格的路由器更适合自由风格的应用程序结构。
我怎样才能做这样的事情:
@app.route("/")
class MyView(MethodView):
def get(self):
return "Hello word"
我在 Flask 官方文档中找不到这样的功能。而且我也没有在互联网上找到任何解决方案或在 Stack Overflow 上找到类似的问题,所以我为这个案例准备了一个片段。
import types
from flask import Blueprint
from flask.views import MethodView
# decorator code
def class_route(self, rule, endpoint, **options):
"""
This decorator allow add routed to class view.
:param self: any flask object that have `add_url_rule` method.
:param rule: flask url rule.
:param endpoint: endpoint name
"""
def decorator(cls):
self.add_url_rule(rule, view_func=cls.as_view(endpoint), **options)
return cls
return decorator
# Usage
# I use `Blueprint` and `MethodView`, but it should work correct with `App` and `View` to.
bp = Blueprint("bp", __name__, template_folder="templates")
@class_route(bp, "/", "my_view")
class MyView(MethodView):
def get(self):
return "Hello world"
# Advanced usage
# Add decorator as class method
bp.class_route = types.MethodType(class_route, bp)
# And use is as bultin decorator
@bp.class_route("/advanced", "advanced_my_view")
class AdvancedMyView(MethodView):
def get(self):
return "Hello world!"
来自烧瓶文档(https://flask.palletsprojects.com/en/1.1.x/views/):
from flask.views import View
class ShowUsers(View):
def dispatch_request(self):
users = User.query.all()
return render_template('users.html', objects=users)
app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))
最后一个字符串转换为函数并向应用程序注册(@app.route(...)
)
我喜欢D.I。并更喜欢下面描述的方法:
class MyBlueprint:
def __init__(self, ...some resources...):
self.resources = ...
self.blueprint = Blueprint('youdomus_blueprint', __name__)
self.blueprint.add_url_rule('/my-route', view_func=self.my_method)
def my_method(self):
...
app = Flask(__name__)
app.register_blueprint(MyBlueprint(...).blueprint)
下面是一个 运行 的例子。示例模块 bp_example.py
包含一些应用程序逻辑 class:
from flask import Blueprint, jsonify, request
class Greeter:
def __init__(self, greetings: str, default_name: str):
self.blueprint = Blueprint('flask_example', __name__)
self.blueprint.add_url_rule('/a-method', view_func=self.a_method)
self.greetings = greetings
self.default_name = default_name
def a_method(self):
return jsonify(f'{self.greetings}, {request.args.get("name") or self.default_name}')
主模块是这样使用的:
def main():
import sys
from bp_example import Greeter
greeter = Greeter(
greetings=sys.argv[1] if len(sys.argv) > 1 else 'Hello',
default_name=sys.argv[2] if len(sys.argv) > 2 else 'World',
)
from flask import Flask
app = Flask(__name__)
app.register_blueprint(greeter.blueprint)
app.run(port=5000)
if __name__ == '__main__':
main()
这里重要的是蓝图路由定义需要一个实例,而不是 class,否则你会以一些全局变量结尾,单元测试会变得一团糟。
Django 风格Class 基于视图的很酷很强大的功能。但是 Flask 风格的路由器更适合自由风格的应用程序结构。 我怎样才能做这样的事情:
@app.route("/")
class MyView(MethodView):
def get(self):
return "Hello word"
我在 Flask 官方文档中找不到这样的功能。而且我也没有在互联网上找到任何解决方案或在 Stack Overflow 上找到类似的问题,所以我为这个案例准备了一个片段。
import types
from flask import Blueprint
from flask.views import MethodView
# decorator code
def class_route(self, rule, endpoint, **options):
"""
This decorator allow add routed to class view.
:param self: any flask object that have `add_url_rule` method.
:param rule: flask url rule.
:param endpoint: endpoint name
"""
def decorator(cls):
self.add_url_rule(rule, view_func=cls.as_view(endpoint), **options)
return cls
return decorator
# Usage
# I use `Blueprint` and `MethodView`, but it should work correct with `App` and `View` to.
bp = Blueprint("bp", __name__, template_folder="templates")
@class_route(bp, "/", "my_view")
class MyView(MethodView):
def get(self):
return "Hello world"
# Advanced usage
# Add decorator as class method
bp.class_route = types.MethodType(class_route, bp)
# And use is as bultin decorator
@bp.class_route("/advanced", "advanced_my_view")
class AdvancedMyView(MethodView):
def get(self):
return "Hello world!"
来自烧瓶文档(https://flask.palletsprojects.com/en/1.1.x/views/):
from flask.views import View
class ShowUsers(View):
def dispatch_request(self):
users = User.query.all()
return render_template('users.html', objects=users)
app.add_url_rule('/users/', view_func=ShowUsers.as_view('show_users'))
最后一个字符串转换为函数并向应用程序注册(@app.route(...)
)
我喜欢D.I。并更喜欢下面描述的方法:
class MyBlueprint:
def __init__(self, ...some resources...):
self.resources = ...
self.blueprint = Blueprint('youdomus_blueprint', __name__)
self.blueprint.add_url_rule('/my-route', view_func=self.my_method)
def my_method(self):
...
app = Flask(__name__)
app.register_blueprint(MyBlueprint(...).blueprint)
下面是一个 运行 的例子。示例模块 bp_example.py
包含一些应用程序逻辑 class:
from flask import Blueprint, jsonify, request
class Greeter:
def __init__(self, greetings: str, default_name: str):
self.blueprint = Blueprint('flask_example', __name__)
self.blueprint.add_url_rule('/a-method', view_func=self.a_method)
self.greetings = greetings
self.default_name = default_name
def a_method(self):
return jsonify(f'{self.greetings}, {request.args.get("name") or self.default_name}')
主模块是这样使用的:
def main():
import sys
from bp_example import Greeter
greeter = Greeter(
greetings=sys.argv[1] if len(sys.argv) > 1 else 'Hello',
default_name=sys.argv[2] if len(sys.argv) > 2 else 'World',
)
from flask import Flask
app = Flask(__name__)
app.register_blueprint(greeter.blueprint)
app.run(port=5000)
if __name__ == '__main__':
main()
这里重要的是蓝图路由定义需要一个实例,而不是 class,否则你会以一些全局变量结尾,单元测试会变得一团糟。