3
5

More than 3 years have passed since last update.

FlaskにVue.jsからGET、POSTする方法

Posted at

ファイル構造はシンプルにこのようにしています。

.
├── app.py
└── templates
    └── index.html

GETする方法

productsが取得したいデータになっています。
jsonifyを使って、JSONデータを返しています。

portは適当につけてます。

app.py
from flask import Flask, render_template, jsonify, request

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False # 文字化け防止

products = [
    {'id': 1, 'name':'商品1', 'price':780},
    {'id': 2, 'name':'商品2', 'price':1280},
    {'id': 3, 'name':'商品3', 'price':1980},
]

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

@app.route('/products')
def get_products():
    return jsonify({'products': products}) # JSONファイルにしてデータを返す

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

デミレータは今回は使っていないですが、
こちらの記事を参考につけています。
!Flask で Vue.js を使おうと思ったら出鼻をくじかれたのでメモ

GETではつけていないですが、次に紹介するPOSTの方ではdelimiterを使ってレンダリングさせています。
(レンダリングの使い方あってるのか不明)

templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    h2 {
      margin-bottom: 0;
    }
  </style>
  <title>Document</title>
</head>
<body>
  <div id="app">
    <h2>GET</h2>
    <button @click="getProducts">GET /products</button>
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      delimiters: ['[[', ']]'],
      methods: {
        getProducts: function() {
          axios.get('/products')
            .then(response => {
              for (const product of response.data.products) {
                console.log(product);
              }
            })
            .catch(error => {
              console.log(error);
            })
          }
  </script>
</body>
</html>

GETのボタンをクリックすると下記のようにログが出力されます。

2021-08-19_18h33_39.png

POSTの実行

今度は商品追加(Create)のAPI,create_product()を作成します。

app.py
from flask import Flask, render_template, jsonify, request

app = Flask(__name__)
app.config['JSON_AS_ASCII'] = False

products = [
    {'id': 1, 'name':'商品1', 'price':780},
    {'id': 2, 'name':'商品2', 'price':1280},
    {'id': 3, 'name':'商品3', 'price':1980},
]

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

@app.route('/product', methods=['POST'])
def create_product():
    post_data = request.get_json() # get_json()でデータの受け取り

    new_product = {'id': products[-1]['id']+1}  # idのみの辞書を作成
    new_product.update(list(post_data.items())) # 上記で作成した辞書にpostで受けたデータを追加(update)

    products.append(new_product)
    return jsonify({'products': products})

if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port='8888')
templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    h2 {
      margin-bottom: 0;
    }
  </style>
  <title>Document</title>
</head>
<body>
  <div id="app" class="container">
    <h2>POST</h2>
    <form @submit.prevent="createProduct">
      <label>商品名
      <input type="text" v-model="newProduct.name">
      </label><br>
      <label>価格 
        <input type="number" v-model.number="newProduct.price"> <!-- 数値データになるようにnumber修飾性をつける -->
      </label><br>
      <input type="submit" value="POST /product">
    </form>
    <br>
    [[ newProduct.name ]]<br> <!-- バインド情報の表示 -->
    [[ newProduct.price ]]
  </div>

  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14"></script>
  <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      delimiters: ['[[', ']]'],
      data: {
        newProduct: {name: '', price: null},
      },
      methods: {
          createProduct: function() {
            axios.post('/product', this.newProduct)
              .then(response => {
                for (const product of response.data.products) {
                  console.log(product);
                }
              })
              .catch(error => {
                console.log(error);
              })
          }
        }
    });
  </script>
</body>
</html>

POSTボタンの下にバインドしたデータも表示されています。
ログでは商品が追加されてかえってきているので、うまくいっています。

2021-08-19_18h48_45.png

はまったこと

methodsの中でメソッドをアロー関数で書こうとしたら、動かなかったです。

// これは動く
methods: function() {}

// アロー関数だと動かない
methods: () => {}

参考情報

axiosのGitHub、Exampleは見やすかったです。

!Vue.jsとFlaskの間でフォーム情報をやり取りする
!axios GitHub

3
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5