我有一个带有 GET 处理程序的 Flask 应用程序,该处理程序将菜谱 ID 作为 URL 参数,它从数据库中检索菜谱,然后呈现它:
@app.route('/recipe/<int:id>', methods=['GET'])
def get(id):
recipe = get_recipe_from_db(id)
return render_template('recipe.html', recipe=recipe)
这会生成类似 /recipe/5
的 URL。我希望菜谱标题成为生成的 URL 的一部分,而不是仅在 URL 中显示 id,例如 recipe/5/lemon-cake
。在第一个请求中,只有 ID 是已知的。
我不确定这样做的巧妙方法是什么。到目前为止,我已经想出了以下内容:
@app.route('/recipe/<int:id>', methods=['GET'])
def get(id):
recipe = get_recipe_from_db(id)
return redirect(url_for('get_with_title', id=id, title=urlify(recipe.title)))
@app.route('/recipe/<int:id>/<title>', methods=['GET'])
def get_with_title(id, title=None):
recipe = get_recipe_from_db(id)
return render_template('recipe.html', recipe=recipe)
这行得通(即当用户访问 /recipe/5
时,它会重定向到 /recipe/5/lemon-cake
),但会遇到相同配方的问题从数据库中检索两次。
有没有更好的方法来解决这个问题?
注意:recipe
对象很大,包含多个字段,我不想不必要地通过网络传递它。
最佳答案
选项1
最简单的解决方案是在收到响应后立即在客户端修改 URL;因此,不需要重定向和/或查询数据库两次。这可以通过使用 history.pushState()
来实现或 history.replaceState()
.
客户端
<!DOCTYPE html>
<html>
<head>
<script>
function modify_url() {
var title = {{recipe.title|tojson}};
var id = {{recipe.id|tojson}};
window.history.pushState('', '', id + "/" + title);
}
</script>
</head>
<h2>Recipe for {{recipe.title}}</h2>
<body onload="modify_url()"></body>
</html>
服务器端
@app.route('/recipe/<int:id>', methods=['GET'])
def get(id):
recipe = get_recipe_from_db(id)
return render_template('recipe.html', recipe=recipe)
您可能还想保留 get_with_title()
路由,以防用户添加书签/共享 URL(包括标题)并希望它可以访问(否则,“未找到” "访问时会返回错误。
选项 2
如果您不希望每次收到新请求时都查询数据库——甚至不希望检索食谱条目的title
(不是每一列)——并且您有足够的数量存储数据的内存,我建议在启动时查询一次数据库(只选择id
和title
)并创建一个字典,这样你就可以快速查找从食谱 id
中获取 title
。请注意,以这种方式,每次对表执行 INSERT/DELETE/etc 操作时,都必须相应地更新该字典。因此,如果您经常对该表执行此类操作,则可能不是解决该问题的最佳方法,最好继续查询该表以检索 title
。
recipes = dict((row[0], row[1]) for row in result) # where row[0] is id and row[1] is title
然后在您的端点:
@app.route('/recipe/<int:id>', methods=['GET'])
def get(id):
title = recipes.get(id)
return redirect(url_for('get_with_title', id=id, title=urlify(title)))
关于python - Flask 重定向数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70841821/