ファイル構造はシンプルにこのようにしています。
.
├── 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のボタンをクリックすると下記のようにログが出力されます。
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ボタンの下にバインドしたデータも表示されています。
ログでは商品が追加されてかえってきているので、うまくいっています。
はまったこと
methodsの中でメソッドをアロー関数で書こうとしたら、動かなかったです。
// これは動く
methods: function() {}
// アロー関数だと動かない
methods: () => {}
参考情報
axiosのGitHub、Exampleは見やすかったです。