使用Flask和vue-cli脚手架,开发vue3.x版本的python web 项目 | 掘金年度征文

4,231 阅读4分钟

使用 flaskvue-cli 脚手架,开发 vue3.x 版本的 python 与 typeScript web 项目

目前 vue3.x 版本已经出来很久了,已经有不少UI库开发者和公司在使用3.x版本了。

代码地址 github地址:github.com/18055975947… 码云地址:gitee.com/guoqiankun/…

一、创建项目

1. 先用 pyCharm 创建 python-flask-vue-web 项目

文件目录

.
├── app.py
├── static
├── templates
└── venv

2. 在文件夹中 使用 vue create vue-web 创建 vue3.x 版本项目

.
├── app.py
├── static
├── templates
├── venv
└── vue-web

3. 添加 vue.config.js 文件

暂不往里面加东西

module.exports = {}

4. 启动项目

cd vue-web
yarn serve

在这里插入图片描述

5. 修改 vue.config.js 文件

我们开发 flask web 项目,最后通过 render_template 来导入文件,但是在 vue 项目中 通过 yarn run build 生成的文件 在 vue-web 文件中,所以配置一个 outputDirindexPath

  • outputDir

    • Type: string
    • Default: 'dist'
    • 当运行 vue-cli-service build 时生成的生产环境构建文件的目录。
  • indexPath

    • Type: string
    • Default: 'index.html'
    • 指定生成的 index.html 的输出路径 (相对于 outputDir)。也可以是一个绝对路径。
module.exports = {
  outputDir: '../static',
  indexPath: '../templates/index.html'
}

为什么要配置 outputDirindexPath

  1. 我们使用 pycharm 创建的项目从上面的 使用 tree 展示的文件夹目录来看,有 templates 模版文件夹 和 static 资源文件夹
  2. 使用的 vue-cli3.x 及以上版本生成的项目打包之后 没有 static 文件夹,只有 jscss 文件夹,而我们通过 Flask 引入静态资源的路径只能有一个,所以需要给 jscss 一个父文件夹

6、yarn run build 打包

tree -I "venv|*node_modules*" -L 2

-I 不展示 venv 目录 和 node_modules 目录

-L 2 展示两个层级

.
├── app.py
├── static
│   ├── css
│   ├── favicon.ico
│   ├── img
│   └── js
├── templates
│   └── index.html
└── vue-web
    ├── package.json
    ├── public
    ├── src
    ├── tsconfig.json
    ├── vue.config.js
    └── yarn.lock

此时可以发现,index.htmljscssimg 都在指定的文件夹中了

二、预览项目

我们通过 yarn run build 打包项目,也在对应的文件夹内生成了文件

此时,回到我们的 app.py 文件中,引入 index.html

from flask import Flask, render_template

app = Flask(__name__)


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


if __name__ == '__main__':
    app.run()

运行此 python 文件

可以看到

Running on http://127.0.0.1:5000/

浏览器打开发现报错,jscss 文件404,只有第一个 html 文件可以找到

在这里插入图片描述

而在 pyCharm 的控制台中也是显示404

在这里插入图片描述

三、修改项目

1. 修改 vue.config.js 文件

文件报错是 404,意思是路径不对

我们在 vue.config.js 中配置 assetsDir

  • assetsDir
    • Type: string
    • Default: ''
    • 放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录。
module.exports = {
  outputDir: '../static',
  indexPath: '../templates/index.html',
  assetsDir: 'static/'
}

配置 assetsDir 项的目的是把 静态资源以及生成的 jscssimg等加载到 static 文件夹下

yarn run build 打包

此时 python-flask-vue-webstatic 文件夹内容

tree static/ 展示 static 文件夹下的内容

static/
├── favicon.ico
└── static
    ├── css
    │   └── app.ca79b516.css
    ├── img
    │   └── logo.82b9c7a5.png
    └── js
        ├── about.71b95ce9.js
        ├── about.71b95ce9.js.map
        ├── app.f47513f4.js
        ├── app.f47513f4.js.map
        ├── chunk-vendors.24202124.js
        └── chunk-vendors.24202124.js.map

2. 修改 app.py 文件

Flask 创建的 app 中添加静态资源目录

from flask import Flask, render_template

app = Flask(__name__,
            static_folder='./static/static')


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


if __name__ == '__main__':
    app.run()

3. 运行 python 文件

重新打开 http://127.0.0.1:5000/

可以发现,此时 jscssimg 引入都正常了,页面也可以正常显示了,但是此时有一个 favicon.ico 404...

所以此时到了对静态资源的项目引入

四、对项目添加静态资源

1. favicon.ico 路径修改

  1. 先在 vue-web/public/ 文件夹下 创建 static 文件夹
  2. favicon.ico 放到 static 文件夹中
vue-web/public/
├── index.html
└── static
    └── favicon.ico
  1. 修改 vue-web/public/ 文件夹下的 index.html 文件,把 favicon.ico 的引入路径修改下
<link rel="icon" href="static/favicon.ico">
  1. yarn run build 打包 vue 项目
  2. 重新运行 app.py 文件
  3. 浏览器重新打开 http://127.0.0.1:5000/

在这里插入图片描述

此时 favicon.ico 可以正常加载

2. 对项目添加一个静态 js ,例如 jquery.js

  1. jquery.js 放到 static 文件夹中
vue-web/public/
├── index.html
└── static
    ├── favicon.ico
    └── jquery.js
  1. index.html 文件中引入 jquery.js
<script src="static/jquery.js"></script>  
  1. home.vue 中打印 $
<script lang="ts">
import { defineComponent } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

declare global {
  interface Window {
    '$': any;
  }
}

export default defineComponent({
  name: 'Home',
  components: {
    HelloWorld
  },
  mounted () {
    console.log(window.$)
  }
})
</script>

在我们运行的 vue 前端项目中可以看到日志

在这里插入图片描述

  1. yarn run build 打包
  2. 重新运行 app.py 文件,打开 pythonhttp://127.0.0.1:5000/ 查看页面

在这里插入图片描述

此时,favicon.ico 和 静态资源的路径引入就正确了,项目可以正常开发了

3. 到此,正常的 vue 项目就可以开发

前端按照 vue 正常开发模式开发页面即可,后端 python 按照 python 代码来写即可。

五、前后端 ajax 请求

前端 web 页面需要调用 python 中的接口,此也是前后端分离中的最重要的一点

1. app.py 中写入一个 返回 随机数的接口 /api/getRandomNum

from flask import Flask, render_template, jsonify
import random

app = Flask(__name__,
            static_folder='./static/static')


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


@app.route('/api/getRandomNum')
def get_random_num():
    res = {
        'getRandomNum': random.randint(1, 100)
    }
    return jsonify(res)


if __name__ == '__main__':
    app.run()

重新运行 app.py 文件

2. vue 项目 引入 axios

  1. vueyarn add axios
  2. main.ts 中引入 axios
import axios from 'axios'

const app = createApp(App)

app.provide('axios', axios)
  1. home.vue 中使用 axios 进行请求
<script lang="ts">
import { defineComponent, inject } from 'vue'
import HelloWorld from '@/components/HelloWorld.vue' // @ is an alias to /src

declare global {
  interface Window {
    '$': any;
  }
}

export default defineComponent({
  name: 'Home',
  components: {
    HelloWorld
  },
  setup () {
    const axios: any = inject('axios')
    axios.get('http://localhost:5000/api/getRandomNum').then((res: object) => {
      console.log(res)
    }).catch((e: any) => {
      console.log(e)
    })
  }
})
</script>
  1. yarn serve 打开页面发现,请求报错,跨域报错

3. 接口跨域问题解决

  1. Flask-CORS

A Flask extension for handling Cross Origin Resource Sharing (CORS), making cross-origin AJAX possible.

Flask扩展,用于处理跨源资源共享(CORS),使得跨源AJAX成为可能。

  1. pip install flask_cors
  2. app.py 引入 flask_cors
  3. 跨域处理
from flask import Flask, render_template, jsonify
from flask_cors import CORS
import random

app = Flask(__name__,
            static_folder='./static/static')
CORS(app)


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


@app.route('/api/getRandomNum')
def get_random_num():
    res = {
        'getRandomNum': random.randint(1, 100)
    }
    return jsonify(res)


if __name__ == '__main__':
    app.run()

  1. 重新运行 app.py 文件
  2. 刷新 vue 项目

在这里插入图片描述

可以看到,接口已经可以正常请求了,正常返回了。

到此,前后端项目都可以正常开发了,ajax 也可以正常请求

六、项目打包并运行

  1. yarn run build 打包 vue 前端项目
  2. app.py 文件运行
  3. 打开 http://127.0.0.1:5000/#/ 查看项目

在这里插入图片描述

代码地址
参考资料

掘金年度征文 | 2020 与我的技术之路 征文活动正在进行中......