【问题标题】:Dynamically generate Flask routes动态生成 Flask 路由
【发布时间】:2016-11-19 22:19:39
【问题描述】:

我正在尝试从列表中动态生成 Flask 中的路由。我想动态生成视图函数和端点,并用add_url_rule 添加它们。

这是我正在尝试做的,但我收到“映射覆盖”错误:

routes = [
    dict(route="/", func="index", page="index"),
    dict(route="/about", func="about", page="about")
]

for route in routes:
    app.add_url_rule(
        route["route"], #I believe this is the actual url
        route["page"], # this is the name used for url_for (from the docs)
        route["func"]
    )
    app.view_functions[route["func"]] = return render_template("index.html")

【问题讨论】:

    标签: python flask


    【解决方案1】:

    这就是我如何让它工作@this-vidor 和@PZP,get page 方法正在查询一个 sqlite db(但它可以是任何 db),通用函数 def 正在循环并在我的实际代码中字典列表也正在从数据库中提取。所以基本上我完成了我需要的。路线是动态的。我可以在 sql 中打开和关闭路由,而不必去 app.py 编辑它们。

    defaultPage = "/"
    
    @app.route(defaultPage)
    def index():
        page = getPage(defaultPage)
        return render_template("index.html", page=page)
    
    
    
    routes = [
        dict(route="/", func="index", page="index"),
        dict(route="/about", func="about", page="about")
    ]
    
    def generic():
        rule = request.url_rule
        page = getPage(rule)
        return render_template('index.html', page=page)
    
    for route in routes:
        app.add_url_rule(
            route["route"], #I believe this is the actual url
            route["page"] # this is the name used for url_for (from the docs)
        )
        app.view_functions[route["func"]] = generic`
    

    【讨论】:

    • 很高兴你能成功!请记住,要使其正常工作,route["func"] 必须始终等于 route["page"](那么为什么要单独定义它们呢?)。这真的不会引发异常吗?因为顶部的代码定义了"/" 端点的路由,循环的第一次迭代也是如此。此外,与在generic 函数中检索/解析request.url_rule 相比,使用可变部分(如我的回答中所述)可能更干净。
    • 特别是因为这样做会完全消除对多个规则定义的需要。
    • @this-vidor - 我将尝试您的方法并使用 app.route("/") 并对其进行测试。我认为这也是一个很好的方法。如果我不清楚自己想要做什么,我深表歉意,我习惯于使用 Java、Coldfusion、C# 和 node.js。我认为某些方法不能很好地转化为 python。我意识到你关于使用 app.route("/page") 的建议更有意义,因为使用只使用一个函数,循环实际上是为每个路由生成一个函数。
    【解决方案2】:

    你有两个可能的解决方案的一个问题。要么:

    1. route[func] 直接引用一个函数,而不是一个字符串。在这种情况下,您不必为 app.view_functions 分配任何内容。

    或者:

    1. 省略app.add_url_rule 的第三个参数,并为app.view_functions[route["page"]] 分配一个函数。代码

      return render_template("index.html")
      

      不是函数。尝试类似

      def my_func():
          return render_template("index.html")
      # ...
      app.view_functions[route["page"]] = my_func
      

    我推荐第一个选项。

    来源:the docs


    替代解决方案:

    在 URL 中使用可变部分。像这样的:

    @app.route('/<page>')
    def index(page):
      if page=='about':
         return render_template('about.html') # for example
      else:
         some_value = do_something_with_page(page) # for example
         return render_template('index.html', my_param=some_value)
    

    【讨论】:

    • 好的,我会试试的
    • 它们没有定义,我想知道是否有办法动态定义它们。原因是我希望我的列表用于生成所有路由。我不知道这是否可能。
    • @Jesse 查看我修改后的答案;但你现在在问别的东西。什么让你对动态生成函数感到困惑?您可以定义一个返回另一个函数的函数,或者返回一个 tupledict 包含一个函数以及您要与该函数关联的名称...
    • 非常感谢,我快到了!我将发布我编写的代码以使其工作。我需要做的最后一件事是传递一个参数。我有并且 {% extends "layout.html" %} 被用作主模板。例如,我有 {% block head %} 寻找正在寻找页面的页面变量。
    • @Jesse 你剩下的问题和你原来的问题有关系吗?目前尚不清楚您所描述的Jinja2 模板与我最近的后续问题有何关联。
    【解决方案3】:

    对 Flask 不太熟悉,所以可能有一种更简洁的方法可以做到这一点。 (如果了解 Flask 的人认为我的方法本质上是错误的,如果他们在评论中解释原因,我很乐意删除我的答案。)现在我已经摆脱了免责声明,以下是我的想法:

    app.route("/") 是一个装饰器函数。 @ 符号只是 index = app.route("/")(index) 之类的语法糖。因此,您应该能够做这样的事情......

    routes = [
        ("/", index),
        ("/about", about)
    ]
    for route, view_func in routes:
        view_func = app.route(route)(view_func)
    

    这将允许您从动态创建的路由和函数创建 Flask 路由。

    【讨论】:

    • 好的,我知道了,我不知道你可以那样做。我会试一试。
    • @pzp 这个解决方案没有什么“固有的错误”,它只是没有表达任何与Flask.add_url_rule 方法不同的地方。 (Flask.route 装饰器在内部使用 Flask.add_url_rule。)您的代码确实解决了 OP 的问题,但是,通过将 view_func 绑定到函数而不是字符串。
    • @this-vidor 好的。我刚刚阅读了add_url_rule 的文档,确实您是对的。我给了你一个赞成票,但为了完整起见,我也会在这里留下我的答案。
    • @pzp 谢谢!我不是出于竞争精神发表评论,而是为了解决您对您的方法是否“天生错误”的不确定性。它在语法上很优雅。
    • 小修正 - 最好添加方法信息:self.route(route, methods = route_methods)(func)
    猜你喜欢
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-12
    • 2020-05-12
    • 2022-11-14
    • 1970-01-01
    相关资源
    最近更新 更多