如何将 Vue.js 与 Flask 结合使用?

Posted

技术标签:

【中文标题】如何将 Vue.js 与 Flask 结合使用?【英文标题】:How can I combine Vue.js with Flask? 【发布时间】:2018-02-23 03:28:01 【问题描述】:

我想同时使用 Vue.js 和 Flask:Vue.js 用于动态前端,Flask 用于后端。我该怎么做?

【问题讨论】:

【参考方案1】:

当使用 vue-cli 或 Webpack 时,可以简化流程。只需创建

vue.config.js 在您的 Vue 项目中,请参阅:Vue config

module.exports = 
    outputDir: "../dist",

    // relative to outputDir
    assetsDir: "static" 
;

然后配置你的烧瓶应用程序:

app.py

from flask import Flask, render_template

app = Flask(__name__,
            static_folder = "./dist/static",
            template_folder = "./dist")


@app.route('/')
def index():
    return render_template("index.html")

注意,flask 中的static_foldertemplate_folder 不能相同。

【讨论】:

你回答中的最后一行在被难倒了很长一段时间后救了我。当您尝试使用相同的静态和模板文件夹时,Flask 不会产生任何有意义的错误,它只是不起作用(对于 static_folder 中的任何内容都是 404)。【参考方案2】:

我最近遇到了这个问题(结合 Vue.js 和 Flask)。

至少有两种方法可以组合它们,具体取决于您是在创建 1) 简单的 Vue.js 应用程序还是 2) 需要使用像 Webpack 这样的模块捆绑器来组合的更复杂的 Vue.js 应用程序Single-File Components 或 npm 包。


简单的 Vue.js 应用:

这实际上是相当简单且非常强大的:

    如果您希望 Vue.js 功能(“应用程序”)位于其自己的页面上,请创建一个新模板 .html 文件。否则,只需打开您希望应用程序所在的任何 .html 模板文件。 这是您的 Vue.js 模板代码所在的位置。

    如果您可以将 Vue.js javascript 代码与 HTML 放在同一个文件中,下面是一个简单的“Hello World”示例模板,您可以使用它来了解 Flask 模板中需要包含的内容文件:

    <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>
    </head>
    <body>
    <div id="app">
        <p> message </p>
    </div>
    <script>
    new Vue(
      el: '#app',
      data: 
        message: 'Hello Vue.js!'
      
    )
    </script>
    </body>
    
    请注意,此示例将 Vue.js JavaScript 代码包含在 Flask 模板文件中,因此您无需单独包含 Vue.js JavaScript。对于较小的项目,这可能更容易。 或者,如果您希望 Vue.js JavaScript 代码位于其自己的文件中:
      在您的static 文件夹中创建一个新的JavaScript 文件,以您要创建的应用程序命名。 这是您的 Vue.js JavaScript 代码所在的位置。 .html 模板文件的底部包含一个脚本标记以包含 Vue.js。 &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"&gt;&lt;/script&gt; 请注意,版本号会发生变化,因此不要只复制该行。您可以获取最新版本的链接here。 同样在该模板文件的底部,包括一个脚本标签以加载您刚刚创建的 JavaScript 文件。 &lt;script src="%% url_for('static', filename='js/YOUR_APP_NAME.js') %%"&gt;&lt;/script&gt;.html 模板文件中创建一个新的div,它的idapp&lt;div id="app"&gt;&lt;/div&gt;

    如果你使用 Jinja2 来渲染你的模板,你需要添加几行代码告诉 Jinja2 不要使用 语法来渲染变量,因为我们需要 Vue 的那些双花括号符号.js。以下是您需要添加到 app.py 的代码:

    class CustomFlask(Flask):
        jinja_options = Flask.jinja_options.copy()
        jinja_options.update(dict(
            variable_start_string='%%',  # Default is '', I'm changing this because Vue.js uses '' / ''
            variable_end_string='%%',
        ))
    
    app = CustomFlask(__name__)  # This replaces your existing "app = Flask(__name__)"
    
    请注意,如果您切换 Flask 的语法,Flask-Bootstrap 将无法工作,因为 Flask-Bootstrap 有自己的模板,仍然包含“”/“”语法。可以看here怎么改Vue.js的语法,比改Flask的语法还要简单。 照常提供页面。 / 照常渲染模板文件。 如果您愿意,可以使用Vue.js 2.0 Hello World JSFiddle 进行更快的原型设计,然后将代码复制到您的.html.js 文件中。 确保小提琴使用的是最新版本的 Vue.js!

简单!


使用 Webpack 的更复杂的 Vue.js 应用:

    Install Node(它带有 npm,这是我们需要的)。 安装vue-cli: npm install -g @vue/cli 新建一个 Vue.js Webpack 项目: vue create my-project 一种方法是创建一个server 文件夹和一个client 文件夹,其中server 文件夹包含Flask 服务器代码,client 文件夹包含Vue.js 项目代码。 另一种方法是将 Vue.js 项目作为文件夹包含在 Flask 项目中。 设置您的 Webpack 配置,以便在 Flask server/templates 文件夹中创建 app.html 文件,并在 server/static/app/ 文件夹中创建 app.html 所需的静态 JavaScript 和 CSS,与静态资产隔离由 Flask 应用的非 Vue 部分使用。 如果您想将 Vue.js 项目与 Flask 项目结合起来,请在包含 Vue.js 项目的文件夹中运行 npm run build,这将生成一个 .html 文件和几个静态文件(JavaScript 和 CSS) .

我对 Webpack 配置所做的确切更改(通过我的 git 提交):

client/build/webpack.dev.conf.js:

new HtmlWebpackPlugin(
-   filename: 'index.html',
-   template: 'index.html',
+   filename: 'app.html',
+   template: 'app.html',

在这里(上图)我将 Vue.js 'launch' 文件的名称更改为 app.html,这样它就不会与我的 Flask 应用程序的 'index.html' 冲突。


client/config/index.js:

module.exports = 
  build: 
    env: require('./prod.env'),
-    index: path.resolve(__dirname, '../dist/index.html'),
-    assetsRoot: path.resolve(__dirname, '../dist'),
-    assetsSubDirectory: 'static',
-    assetsPublicPath: '/',
+    index: path.resolve(__dirname, '../../server/templates/app.html'),
+    assetsRoot: path.resolve(__dirname, '../../server/static/app'),
+    assetsSubDirectory: '',
+    assetsPublicPath: '/static/app',

这里(上图)我正在设置 app.html 文件和静态资源的创建位置。

因为我们正在指导 Webpack 在 Flask 的“静态”文件夹 (/static/app/) 中生成静态资源...

    html 文件中包含这些资产的相对 URL 将由 Webpack 自动正确设置。 例如:src=/static/app/js/app.f5b53b475d0a8ec9499e.js 当查询这些 URL 上的文件时,Flask 将自动知道如何提供它们,因为它们位于 static/ 文件夹中,Flask 假定该文件夹具有 /static/etc. URL。 唯一需要 Flask 路由的生成文件是 app.html 文件。

client/build/webpack.prod.conf.js:

new HtmlWebpackPlugin(
  filename: process.env.NODE_ENV === 'testing'
-    ? 'index.html'
+    ? 'app.html'
    : config.build.index,
-  template: 'index.html',
+  template: 'app.html',

这里(上图)我只是重命名了“启动”页面,与webpack.dev.conf.js 中的相同。


routes.py:

@web_routes.route('/app')
@login_required
def app():
    if current_user.datetime_subscription_valid_until < datetime.datetime.utcnow():
        return redirect(url_for('web_routes.pay'))

    return render_template('app.html')

这里(上图)是我的渲染函数。我正在使用 Flask 的蓝图功能 (&lt;blueprint_name&gt;.route),但您不必这样做。

【讨论】:

如果你提供链接 github 项目和设置会很好:)。我也偶然发现了这个问题(你回答的第二部分),但问题太多了。 这是个好主意...不幸的是我可以看到这需要我一段时间。我可能会在某个时候解决它。如果您(或其他人)最终这样做,我会将链接添加到答案中。 另外,如果您从头开始,我建议您看看 Nuxt (nuxtjs.org)。 “简单”的方式似乎不适用于外部模块。 @maugch 您尝试使用的外部模块是什么?

以上是关于如何将 Vue.js 与 Flask 结合使用?的主要内容,如果未能解决你的问题,请参考以下文章

Heroku 部署混乱:Vue.js 前端与 Flask 后端

使用 Vue.js 和 Flask 实现全栈单页面应用

由于不允许的预检标头,Vue.js 前端与 Flask 后端 CORS 问题交互

使用 FLASK 将 REST API 与 Web 界面相结合的最佳实践

将 Greenleets 与 Flask 和标准线程相结合

将 moment.js 与 vue.js 一起使用