Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
126
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

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

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

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
126
Help us understand the problem. What are the problem?