iMind Developers Blog

iMind開発者ブログ

Vue.jsとFlaskで連携する

概要

Flaskで作成したAPIとVue.jsで通信して画面を表示するページを作成するローカル環境を作る。

バージョン情報

  • flask==1.1.1
  • Flask-Cors==3.0.9
  • Flask-RESTful==0.3.8

  • "vue": "^2.6.11"

  • "vue-router": "^3.4.8"
  • "axios": "^0.21.0"
  • @vue/cli 4.5.7

Flaskのアプリの生成

事前にFlaskのAPIを作っておく。

アプリの内容は簡単にxというパラメータを受けたらそれを2倍にして返すというもの。

requirements.txt の内容は下記あたり。

flask==1.1.1
Flask-Cors==3.0.9
Flask-RESTful==0.3.8

app.py

import random
from flask import Flask, request
from flask_restful import Api, Resource, fields, marshal_with
from flask_cors import CORS

app = Flask(__name__)
CORS(app)
api = Api(app)

resource_fields = {
    'value': fields.Float
}

class TwoTimesValue(object):
    def __init__(self, value):
        self.value = value * 2

class TwoTimes(Resource):
    @marshal_with(resource_fields)
    def post(self):
        json_data = request.get_json(force=True)
        app.logger.info(json_data)
        return TwoTimesValue(json_data['param'])

api.add_resource(TwoTimes, '/')

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

起動

$ python app.py

curlで動作確認

$ curl --header "Content-Type: application/json" \
  --request GET \
  --data '{"param":2}' \
  http://localhost:5000/

結果

{
    "value": 4.0
}

これで数値を2倍するAPIが作れた。

APIを呼んで結果を表示するVue.jsアプリ

vue-cliからプロジェクトの生成。

$ vue create axios-example
$ cd axios-example

API通信用にaxiosとansi-regexを入れておく。あとvue-routerも。

$ yarn add axios ansi-regex vue-router

今回はクエリストリングの値からAPIを呼び出す版と、フォームの入力値から呼び出す版の2つを用意してみる。

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

new Vue({
  render: h => h(App),
  router,
}).$mount('#app')

router.js。 / の場合はクエリストリングから、/form_version の場合はformの内容から取るコンポーネントを呼ぶ。

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    component: () => import("./components/QueryVersion"),
    props: (route) => ({ param: Number.parseInt(route.query.param, 0) })
  },
  {
    path: '/form_version',
    component: () => import("./components/FormVersion"),
  },
]

export default new VueRouter({
  mode: 'history',
  routes,
})

app.vue。router-viewとrouter-linkを定義。router-linkではparamに3を入れてクエリ文字列を送る。

<template>
  <div id="app">
    <router-view></router-view>
    <ul>
      <li>
        <router-link v-bind:to="{path: '/', query: {param: 3}}">query version</router-link>
      </li>
      <li>
        <router-link to="/form_version">form version</router-link>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'App',
}
</script>

./components/QueryVersion.vue。クエリ版の記述。Routerからクエリ文字列がparamに入れられるので、それを利用してaxiosでlocalhost:5000へパラメータを送る。

<template>
  <div id="query-version">
    {{ param }} * 2 = {{ value }}
  </div>
</template>

<script>
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:5000';

export default {
  name: 'query-version',
  data: function() {
    return { value: 0 }
  },
  props: {
    param: Number,
  },
  mounted: function() {
    this.updateValue()
  },
  watch: {
    param: function() {
      this.updateValue()
    },
  },
  methods: {
    updateValue: function() {
      const vm = this;
      axios.post("/", 
        {
          'param': vm.param
        },
        {
          headers: {
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application / x-www-form-urlencoded',
          }
        }
      ).then(function(response){
        vm.value = response.data.value
      } );
    }
  }
}
</script>

mountedでまずAPIを呼び出す。またparamをwatchしておいて変更された場合にも呼び出す。

これで http://localhost:8080/?param=4 を呼び出すと4でAPIが呼ばれて8が返り、その値が画面に表示される。

f:id:mwsoft:20201103221556p:plain

続いてフォーム版。

components/FormVersion.vue

<template>
  <div id="form-version">
    <p><input v-model="param" placeholder="input number"></p>
    <p>{{ param }} * 2 = {{ value }}</p>
  </div>
</template>

<script>
import axios from 'axios'
axios.defaults.baseURL = 'http://localhost:5000';

export default {
  name: 'form-version',
  data: function() {
    return { 
      'param': null,
      'value': null,
    }
  },
  watch: {
    param: function(newParam) {
      this.updateValue(newParam)
    },
  },
  methods: {
    updateValue: function(param) {
      const vm = this;
      axios.post("/", 
        {
          'param': Number(param)
        },
        {
          headers: {
            'X-Requested-With': 'XMLHttpRequest',
            'Content-Type': 'application / x-www-form-urlencoded',
          }
        }
      ).then(function(response){
        vm.value = response.data.value
      } );
    }
  }
}
</script>

paramの内容をwatchして変更があればAPIを呼ぶ。

これでフォームに入力があるたびにAPIが呼ばれて画面に値が出力される。

f:id:mwsoft:20201103221816p:plain

改定履歴

Author: Masato Watanabe, Date: 2020-11-03, 記事投稿