Help us understand the problem. What is going on with this article?

Vue.js(vue-cli)とFlaskを使って簡易アプリを作成する【後半 - サーバーサイド編】

More than 1 year has passed since last update.

vueflask.png

どうもmiyachi(@_38ch)です。
前回の記事
Vue.js(vue-cli)とFlaskを使って簡易アプリを作成する【前半 - フロントエンド編】
で、フロントエンドVue.js、サーバーサイドFlaskで作る簡易SPAのフロントエンドの紹介をしました。

今回はサーバーサイド(Flask側)の作り方を書いていきます。
なお、サーバーサイドにはPython3.6を使っています。

backendディレクトリを作成

ディレクトリを切って、virtualenvで仮想環境を作ります。

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

アクティベートします。

$ source venv/bin/activate

アクティベートが完了したら、Flaskをインストールします。

(venv) pip install Flask

ルートディレクトリ(frontend, backendと同じディレクトリ)に戻って、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")

このrun.pyは一般的なFlask starterとは少し異なります。
どこが違うかというと、static_folderとtemplate_folderの部分。
templateファイルはfrontendから生成されたものを読み込む必要があるので、ここでパスを指定しています。

Flaskサーバーを起動

以下を実行してあげると、Flaskサーバーが立ち上がります。

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

localhost:5000で確認できます。
最初のページはうまく表示されますが、/aboutに行くとNOT FOUNDになってしまいました。

image.png

run.pyの設定を少し変えてあげましょう。

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

これで正常にaboutページが表示されるはず。

APIエンドポイントを追加

1-100でランダムな数値を返すシンプルなAPIを作成します。
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")

'/api/random'にリクエストを投げるとランダムな数値を以下のようなJSON形式で返してくれる。

{
  "randomNumber": 36
}

ブラウザで localhost:5000/api/random にアクセスしてテストできます。
image.png

サーバーサイドで動作が確認できたら、それをフロントから呼べるようにしましょう。
Home.vueを以下のように修正します。

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>
import axios from 'axios'

export default {
  data () {
    return {
      randomNumber: 0
    }
  },
  methods: {
    getRandom () {
      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)
      })
  }
},
  created () {
    this.getRandom()
  }
}
</script>

大まかに説明すると、

  • randomNumberは0で初期化されている。
  • ボタンをクリックすると、getRandomが走る。
  • getRandomが走ると、サーバーサイドにHTTPリクエストが送られ、ランダムな数値が返ってくる。
  • randomNumberが更新されて、画面の値が変わる

という感じです。

backendにHTTPリクエストをなげるためには、axiosというライブラリを使用します。

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

フロントを更新したので、再度 npm run build を実行して、
localhost:5000から確認します。

Jun-03-2018 1-02-26 PM.gif

正常にランダムな数値を取得するAPIを実装できました。
間違え、ご指摘などあれば、コメント欄にいただけると助かります。

ソースコード

今回使用したコードはこちらにあげておきます。
もしお役にたったらStarいただけると嬉しいです。
https://github.com/miyachin/vue-flask-sample

mitch0807
猫と銭湯が好きな文系出身若手エンジニアです。 大学ではコンピューターサイエンス学んでないので、お手柔らかにお願いします。
https://miyach.in
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away