如何在基于类的视图中使用烧瓶路径?

时间:2019-03-19 19:29:57

标签: python flask routing class-based-views

Django样式基于类的视图具有强大的功能。但是Flask风格的路由器更适合应用程序结构的自由风格。 我该怎么做:

@app.route("/")
class MyView(MethodView):
    def get(self):
        return "Hello word"

3 个答案:

答案 0 :(得分:2)

来自烧瓶文档(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(...)

答案 1 :(得分:0)

我在烧瓶的官方文档中找不到该功能。而且我也没有在Internet上找到任何解决方案,也没有在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!"

答案 2 :(得分:0)

我喜欢 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 包含一些应用程序逻辑类:

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()

这里重要的是蓝图路由定义需要一个实例,而不是一个类,否则你会以一些全局变量结束,单元测试就会变得一团糟。