如何使用 Flask 创建基于模板的动态 URL

时间:2021-07-10 12:55:05

标签: python flask

我有一个像这样的烧瓶路线:

@app.route('/product/<string:slug>')
def product(slug):
    # some codes...
    return render_template('product.html', product=product)

不同的客户使用该项目(不同的网站,相同的基础架构)。每个客户都希望产品 URL 不同。喜欢;

asite.com/product-nike-shoe-323

bsite.com/nike-shoe

csite.com/product/nike-shoue

对比对比

如何设置来自数据库的 URL 结构?

喜欢:

url_config = "product-{product_name}-{product_id}"

url_config = "product-{product_id}"

注意:请不要重定向。

2 个答案:

答案 0 :(得分:2)

当您在这里说“数据库”时,我不是 100% 清楚您指的是什么。根据上下文,我推断您可能在谈论 Flask Config object。如果是这种情况,您只需在 setting up the app configuration 之后立即注册您的视图函数。只需调用 app.add_url_rule() 即可注册配置中的 URL 模式以指向您选择的视图函数。

但是,如果您正在谈论 SQL 或 NoSQL 数据库,并且您已经构建了一个 Web UI 来注册路由,那么不要失望。 Flask 路由可以在任何时候注册到应用程序对象。在 Flask 应用程序生命周期中,您将无法再注册路由!

注册路由所做的只是在 URL 模板和端点名称(一个不透明的字符串)之间创建映射。大多数情况下,您还会注册一个要调用的函数来处理特定端点,而大多数情况下,Flask 会从该函数中推断出端点名称。一旦在映射中注册,任何下一个传入请求都可以路由到给定端点的函数。

因此,Flask 保留了两张地图:

也就是说,有用于删除更改 url注册的API(当然,除了重新启动服务器)。您无法更改 url 路由、给定路由的端点名称或哪个端点映射到哪个函数。该框架的意图是您在第一次启动服务器时尽早注册您的路由,通过在导入或绑定到应用程序时直接运行的代码(蓝图和 Flask 扩展执行后者)。大多数 Flask 应用程序将创建他们的 Flask 实例,注册他们所有的路由和扩展,然后将实例传递给 WSGI 服务器以进行请求调度,就是这样。但是在此之后,实现中没有任何内容阻止您注册更多路由。

如果你想从数据库信息中注册 URL 路由,你至少要注意以下两点:

  1. 在启动时注册现有路由。与数据库建立连接后,检索现有路由并注册它们。
  2. 如果有新条目添加到数据库中,请注册新路由。

首先:如果我要实现这样的东西,我会使用一个视图函数。通过分别查看 request.url_rulerequest.endpoint,您始终可以找出匹配的 url 规则以及它映射到的端点名称。

接下来,我将从数据库中为每个 url 规则显式生成端点名称。在名称中使用主键;您希望能够从端点名称中找到数据库行,反之亦然。你如何做到这一点取决于你;假设您知道如何执行此操作,并且您有两个名为 pk_from_endpoint()endpoint_from_pk() 的函数。

你的视图函数看起来像这样:

from flask import request

def product_request(**kwargs):
    key = pk_from_endpoint(request.endpoint)
    row = database_query(key)
    # … process request

您为给定的数据库行注册一个路由:

app.add_url_route(row.url_config, endpoint_from_pk(row.id), product_request)

如前所述,您不能更改 URL 注册。但是,只要不经常更改这些 URL,您就可以随时添加注册,对于任何旧条目,请使用 abort(404) 返回 404 Not Found 响应。

答案 1 :(得分:0)

这在 Flask 的路由系统中是不可能的。网址映射应该在启动时定义,之后不会更改。

但是,如果您有一些需要动态部分的特定路径(例如 /product/WHATEVER),那么您可以为 /product/<slug> 注册一个路径并在您的视图函数中查询数据库。


也就是说,如果您真的希望在数据库中使用 URL 规则,并且不介意在启动期间连接到您的数据库(通常这很丑陋),那么没有什么可以阻止您在启动时查询数据库并根据以下内容定义 URL 规则来自数据库的数据。相当丑陋,但可行。

示例:

with app.app_context():
    url_map = {u.endpoint: u.rule for u in URLRules.query}

@app.route(url_map['foo'])
def foo():
    ...

当然,除非您在一个地方为所有端点使用 app.add_url_rule() 而不是 @app.route() 装饰器,否则这样做会更难很好地构建您的应用程序。

当然蓝图也是如此。

相关问题