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('/&lt;path:path&gt;') 匹配任何东西。设置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 路由的主要内容,如果未能解决你的问题,请参考以下文章

doraemon的python Flask框架 路由和配置

flask的路由

使用 Flask 和 React 的 localhost CORS 错误

flask笔记(七):简单路由设置

Flask - 路由

Flask之三:路由