Flask 和 React 路由
Posted
技术标签:
【中文标题】Flask 和 React 路由【英文标题】:Flask and React routing 【发布时间】:2015-08-17 16:10:15 【问题描述】:我正在使用 React 构建 Flask 应用程序,但最终遇到了路由问题。
后端负责成为一个 API,因此一些路由看起来像:
@app.route('/api/v1/do-something/', methods=["GET"])
def do_something():
return something()
以及通往 React 的主要路线:
@app.route('/')
def index():
return render_template('index.html')
我在 React 应用程序中使用 react-router,一切正常,react-router 将我带到 /something
,我得到了渲染视图,但是当我在 /something
上刷新页面时,Flask 应用程序会处理这个电话,我得到Not Found
错误。
什么是最好的解决方案?我正在考虑将所有未调用 /api/v1/...
的调用重定向到 /
这并不理想,因为我将返回我的应用程序的主页,而不是呈现 React 视图。
【问题讨论】:
如果您不希望后端处理 url,最快最简单的方法是不使用 HTML5 历史 API。停用它会导致像/#/something
这样的hashbang url,重新加载它们总是会触发后端的/
视图。否则,您需要在后端处理请求或将它们重定向到您的 react 应用程序,如果请求的 url 不是/
,则需要分析请求并触发位置更改。
这似乎是某种解决方案,谢谢!
我认为这不是一个好的解决方案。现在是 2015 年,你真的应该使用 History API。
@DanAbramov 完全正确,但如何?
可能还有另一种方法——你可以简单地在 .htaccess 文件中编写一个重写语句,这样每次特定的#something
来自 react-router 而不是烧瓶。如果 URL 基于某种模式,这可能是一种有效的解决方案,以免浪费时间。
【参考方案1】:
我们为此使用了catch-all URLs。
from flask import Flask
app = Flask(__name__)
@app.route('/', defaults='path': '')
@app.route('/<path:path>')
def catch_all(path):
return 'You want path: %s' % path
if __name__ == '__main__':
app.run()
您还可以加倍努力,重用Flask routing
系统以将path
匹配到与客户端相同的路由,这样您就可以将客户端需要的数据作为JSON 嵌入HTML 响应中。
【讨论】:
如果所有路由都将被引导以捕获所有功能,当我从前端进行 ajax 请求调用时,您将如何分离后端 api 路由和响应路由? @shangyeshen 在 catch-all 之前注册 API 路由,使其具有优先权。 在某处有完整的例子吗?这里的代码没有像上面的例子那样做任何索引渲染,我无法以一种有效的方式将两者结合起来。 找到了。在我弄清楚记录不充分的 Flask 参数之前,我无法让@app.route('/<path:path>')
匹配任何东西。设置static_url_path=""
不好。我最终得到了static_url_path="/public", static_folder="../public"
。然后我返回一个静态:return app.send_static_file("index.html")
,带有硬编码的"/public/..."
url。另外,请看:reddit.com/r/reactjs/comments/42pn95/reactrouter_and_flask_404(不是我)。
这是我使用了一段时间的解决方案,直到我需要使用 React.lazy
将我的包分成几部分。 React.lazy
想要从 path
获取捆绑包部分,而不是烧瓶正在使用的静态目录。有什么想法吗?【参考方案2】:
也许作为之前答案的扩展。这为我解决了问题:
from flask import send_from_directory
@app.route('/', defaults='path': '')
@app.route('/<path:path>')
def serve(path):
path_dir = os.path.abspath("../build") #path react build
if path != "" and os.path.exists(os.path.join(path_dir, path)):
return send_from_directory(os.path.join(path_dir), path)
else:
return send_from_directory(os.path.join(path_dir),'index.html')
【讨论】:
你不能用一个普通的 path_dir 替换空的 os.path.join(path_dir) 吗?【参考方案3】:出于某种原因,包罗万象的 URL 对我不起作用。我发现使用烧瓶 404 处理程序会产生完全相同的结果。它会看到 url 并将其传递给路由器处理它的位置。
@app.errorhandler(404)
def not_found(e):
return app.send_static_file('index.html')
【讨论】:
这很好用!感谢分享!【参考方案4】:只是为了通知处理错误 404,render_template 对我来说非常有效。
@app.errorhandler(404)
def not_found(e):
return render_template("index.html")
【讨论】:
以上是关于Flask 和 React 路由的主要内容,如果未能解决你的问题,请参考以下文章