Flask and Vue.js use to build full-stack single-page application

In this tutorial, I will show you how to connect single-page application and back-end Vue's Flask.

Simply put, if you want to use Vue framework Flask is no problem. But there is an obvious problem in practice is Flask template engine Jija and Vue as to render the use of double braces for grammar and conflicts Jinja templates Vue, here are a good solution   here Wallpaper .

I want to be different. Make a Vue.js do with the front end (with a single page components, HTML5 historical patterns "vue-router" and other good characteristics), how to do the back-end with a Flask single page application? Simply put, this application should look like this:

  • Flask used to drive a "index.html" contains Vue.js app, and
  • I used the front-end development process characteristics Webpack and it offers all the cool
  • Flask I have access to the port from the SPA API
  • When I developed the front end, I was able to run Node.js api access port

Sounds interesting, right? let us start.

The following are links to all the code
https: //github.com/oleg-agapov/flask-vue-s ...

Client

In order to generate the basic Vue.js file structure, I will use the  VUE-cli . If you do not install it, run the following command:

$ npm install -g vue-cli

The client and back-end code will be split into different folders, run the following command to initialize the front part:

$ Mkdir flaskvue 
$ cd flaskvue 
$ vue init webpack fron intuitive

Below is my settings during installation:

  • Vue build --- Runtime only
  • Install vue-router? --- Yes
  • Use ESLint to lint your code? --- Yes
  • Pick an ESLint preset --- Standard
  • Setup unit tests with Karma + Mocha? --- No
  • Setup e2e tests with Nightwatch? --- No

Next:

Cd frontend $ 
$ npm install 
# run the following command after the installation is complete 
$ npm run dev

Here, you should install the Vue.js it! Let's add some pages.

 In the  frontend/src/components Add folder  Home.vue and  About.vue two files. And add the following to the corresponding file:

// content Home.vue file
 <Template> 
  <div> 
    <the p-> Home </ the p-> 
  </ div> 
</ Template>

with

// content About.vue file
 <Template> 
  <div> 
    <the p-> About </ the p-> 
  </ div> 
</ Template>

We will use them correctly identify our current location (the address bar). Now, we need to change the  frontend/src/router/index.js file to present our new component:

import Vue from 'vue'
import Router from 'vue-router'
const routerOptions = [
  { path: '/', component: 'Home' },
  { path: '/about', component: 'About' }
]
const routes = routerOptions.map(route => {
  return {
    ...route,
    component: () => import(`@/components/${route.component}.vue`)
  }
})
Vue.use(Router)
export default new Router({
  routes,
  mode: 'history'
})

If you try to enter  localhost:8080 and  localhost:8080/aboutyou should see the page.

To create a package containing static assets, we are almost ready to build a project. Until then, let us redefine the output directory for them. In the front-end  frontend/config/index.js index. Found under a set

index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),

They then becomes as follows

index: path.resolve(__dirname, '../../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../../dist'),

因此,带有 html/css/js 包的 /dist 文件夹将与 /frontend 具有相同的级别。现在您可以运行 $ npm run build 来创建一个包。

Back-end

我将使用 python 3.6 来进行 flask 应用程序开发。在根目录 /flaskvue 下创建一个子目录来放后端代码,并在子目录中初始化一个虚环境: 

$ mkdir backend
$ cd backend
$ virtualenv -p python3 venv

执行下面的命令来激活虚环境 (macOs 操作系统):

$ source venv/bin/activate

在 windows 中激活虚环境请参考此文档 docs.

在虚环境中安装 flask:

(venv) pip install Flask

现在我们开始开发 flask 应用程序。在根目录下创建 run.py 文件:

(venv) cd ..
(venv) touch run.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 starter Hello world 代码略有不同。主要的不同之处在于,我们指定了静态和模板文件夹来用前端包指向 /dist 文件夹,在根文件夹中运行 Flask 服务:

(venv) FLASK_APP=run.py FLASK_DEBUG=1 flask run

这将在 localhost:5000 上启动一个 web 服务器。FLASK_APP 指向服务器启动文件,FLASK_DEBUG=1 将在调试模式下运行。如果一切都是正确的,您将看到熟悉的主页,您在 Vue 上所做的。

与此同时,如果你试图添加一个 /about 页面。 Flask 将抛出一个页面未找到的错误。 确实如此,因为我们在 vue-router 中使用了 HTML5 历史模式,我们需要去 配置我们的服务器 让所有路由跳转到 index.html. 这个在 Flask 中很容易做到 。将现有的路由修改为如下内容:

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return render_template("index.html")

新的 URL 链接 localhost:5000/about 将会跳转到 index.html ,并且 vue-router 将会自己处理其余的事情。

 

添加 404 页面

因为我们定义了一个将所有请求跳转到 index.html 的路由,因此 Flask 将无法捕获到 404 错误(以及不存在的页面),将一些找不到页面的请求也跳转到 index.html。所以我们需要在 Vue.js 的路由文件中设置一条路由规则去处理这种情况。

在 frontend/src/router/index.js 中添加一行:

const routerOptions = [
  { path: '/', component: 'Home' },
  { path: '/about', component: 'About' },
  { path: '*', component: 'NotFound' }
]

这里的 '*' 是 vue-router 中的通配符,用以代表任何除了我们已经定义好的路由之外的其他情况。 接下来我们在 /components 文件夹中创建一个 NotFound.vue 文件,并写几行简单的代码:

// NotFound.vue
<template>
  <div>
    <p>404 - Not Found</p>
  </div>
</template>

现在通过运行 npm run dev 来重新运行前端服务器,并尝试一些不存在的 URL 链接,例如 localhost:8080/gljhewrgoh 。你就可以看到 “Not Found” 的消息提示了.

添加 API 端点

我的 'Vue.js/Flask' 的最后一个例子。 'Vue.js/Flask' 教程将在服务器端创建 API 并在客户端发送。我将创建一个简单的端点,它将返回一个从 1 到 100 的随机数。

打开 run.py 并添加:

from flask import Flask, render_template, jsonify
from random import *
app = Flask(__name__,
            static_folder = "./dist/static",
            template_folder = "./dist")
@app.route('/api/random')
def random_number():
    response = {
        'randomNumber': randint(1, 100)
    }
    return jsonify(response)
@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    return render_template("index.html")

首先,我从 'Flask' 库导入了 'random' 库和 'jsonify' 函数。然后我添加了新的路由 ' /api/random ' 来返回 JSON,如下所示:

{
  "randomNumber": 36
}

您可以通过导航到 localhost:5000/api/random 来测试此路由。

此时,服务器端工作已经完成。是时候在客户端展示了。我会改 Home.vue 组成来显示我的随机数:

 

<template>
  <div>
    <p>Home page</p>
    <p>Random number from backend: {{ randomNumber }}</p>
    <button @click="getRandom">New random number</button>
  </div>
</template>

<script>
export default {
  data () {
    return {
      randomNumber: 0
    }
  },
  methods: {
    getRandomInt (min, max) {
      min = Math.ceil(min)
      max = Math.floor(max)
      return Math.floor(Math.random() * (max - min + 1)) + min
    },
    getRandom () {
      this.randomNumber = this.getRandomInt(1, 100)
    }
  },
  created () {
    this.getRandom()
  }
}
</script>

 

在这个阶段,我只是在客户端模拟随机数生成过程。所以,这个组件是这样工作的:

  • 初始化变量 randomNumber 等于 0
  • 在 methods 部分 ,我们又 getRandomInt(min, max) 方法, 它将返回一个指定范围内的数字, getRandom 函数,将调度之前的函数,并将其值赋给 randomNumber
  • 创建组件方法后,将调用 getRandom 来初始化 randomNumber
  • 触发按钮事件后,我们将调用 getRandom 获取新数字

在前端,现在在首页你应该看到我们的随机数产生。让我们把它连接到后端。
为此,我们将使用 ' axios' 库,它允许我们发出 HTTP 请求并返回带有 JSON 响应的 JavaScriptPromise。让我们安装它:

 

(venv) cd frontend
(venv) npm install --save axios

 

再次打开 Home.vue 文件并 在 <script> 区域添加一些更改:

import axios from 'axios'
methods: {
  getRandom () {
    // this.randomNumber = this.getRandomInt(1, 100)
    this.randomNumber = this.getRandomFromBackend()
  },
  getRandomFromBackend () {
    const path = `http://localhost:5000/api/random`
    axios.get(path)
    .then(response => {
      this.randomNumber = response.data.randomNumber
    })
    .catch(error => {
      console.log(error)
    })
  }
}

在最开始我们导入 axios 库。然后有一个新方法 getrandomfrombackend,它将使用 AXIOS 异步访问 API 并检索结果。最后,方法 getRandom 现在应该使用 getRandomFromBackend 函数来获取随机值。

保存文件,转到浏览器中,再次运行开发服务器,刷新 localhost:8080 然后… 您应该在控制台中看到一个错误,并且没有随机值。但别担心,一切都正常。我们得到 [cors](http s://developer.mozilla.org/en-us/docs/web/http/cors)错误,这意味着我们的 flask 服务器 API 默认关闭到其他 Web 服务器(在我们的情况下,它是运行 vue.js 应用程序的 node.js 服务器)。如果您使用 npm run build 创建一个 bundle 并打开 localhost:5000(就是 flask 服务器),您将看到正在工作的应用程序。但是,每次对客户端应用程序进行一些更改时,创建一个包并不十分方便。

让我们使用 Flask 的 CORS 插件,这将允许我们为 API 访问创建规则。 插件名为 [flask-cors](http://flask-cors.readthedocs.io/en/latest/),让我们安装它

 

(venv) pip install -U flask-cors

 

您可以阅读插件的文档,文档中更好地说明了再服务器上启用 CORS 的方法。 我将使用特定于资源的方法并将 {“origin”“:”*“} 应用于所有 / api / * 路由(所以每个人都可以使用我的 / api 端点)。在 run.py中:

 

from flask_cors import CORS
app = Flask(__name__,
            static_folder = "./dist/static",
            template_folder = "./dist")
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})

 

通过以上更改,您可以直接从前端开发服务器调用 Flask API。

更新:

实际上,如果你通过 Flask 提供静态文件,则不需要更新 CORS 扩展。 感谢 [Carson Gee](https://github.com/carsongee)这个技巧

解决思路如下。 如果应用程序处于调试模式,它将只代理我们的前端服务器。 否则(在生产模式)提供静态文件。 以下是实现的代码:

 

import requests

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def catch_all(path):
    if app.debug:
        return requests.get('http://localhost:8080/{}'.format(path)).text
    return render_template("index.html")

 

实现方式简单而优雅,像魔术一样✨!

现在,您拥有一个使用自己喜欢的技术构建的全栈应用程序啦。

后记

最后,我想就如何改进此解决方案说几句话。

首先,只有在您想要让 API 可供外部服务器访问时才使用 CORS 扩展。 否则只需使用代理前端开发服务器的技巧。

另一项改进是避免在前端硬编码 API 路由。 也许您需要创建一个包含 API 路由名称的词汇集。 因此,当您更改 API 路由时,您只需刷新这个词汇集即可。 前端关于路由名称的代码不需要更改。

通常在开发过程中,您将至少需要两个终端窗口:一个用于 Flask ,另一个用于 Vue.js 。 在生产环境中,你将不需要为 Vue 运行单独的 Node.js 服务器。

获取源码及相关视频教程加群887934385 免费领取

Guess you like

Origin www.cnblogs.com/pypypy/p/11998899.html