我有一个烧瓶路线,如下所示:
@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}"
注意:请不要重定向。
当你在这里说"数据库"时,我不是100%清楚你指的是什么。根据上下文,我推断您可能在谈论Flask Config对象。如果是这种情况,您只需在设置应用程序配置后立即注册查看功能即可。只需调用app.add_url_rule()
即可从配置中注册URL模式,指向您选择的视图函数。
然而,如果你谈论的是SQL或NoSQL数据库,并且你已经构建了一个用于注册路由的web UI,那么就不要发布。Flask路由可以在任何时候向应用程序对象注册。在Flask应用程序的生命周期中,没有一点是你不能再注册路线的!
注册路由所做的就是在URL模板和端点名称(一个不透明的字符串(之间创建映射。大多数时候,您还注册了一个要调用的函数来处理特定的端点,大多数时候,Flask从该函数推断端点名称。一旦在映射中注册,任何下一个传入请求都可以路由到给定端点的函数。
因此,Flask保留了两张地图:
- 从url路由->端点名称:
Flask.url_map
- 从端点名称->函数:
Flask.view_functions
也就是说,有API用于删除或更改url注册(当然,除了重新启动服务器(。您不能更改url路由、给定路由的端点名称或哪个端点映射到哪个函数。该框架的意图是在首次启动服务器时尽早注册路由,通过导入或绑定到应用程序时直接运行的代码(Blueprint和Flask扩展完成后者(。大多数Flask应用程序都会创建他们的Flask实例,注册所有路由和扩展,然后将该实例传递给WSGI服务器进行请求调度,仅此而已。但在此之后,实现中没有任何内容可以阻止您注册更多路由。
如果你想从数据库信息中注册URL路由,你必须至少注意以下两件事:
- 在启动时注册现有路由。一旦建立了与数据库的连接,就可以检索现有路线并进行注册
- 如果数据库中添加了一个新条目,请注册一个新路由
首先:如果我要实现这样的东西,我会使用一个视图函数。您总是可以通过分别查看request.url_rule
和request.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响应。
这在Flask的路由系统中是不可能的。URL映射应该在启动时定义,之后不会更改。
但是,如果您有一些特定的路径需要动态部件(例如/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()
装饰器。
当然,蓝图也是如此。