ひばりログ

Apple関連やプログラミングなど趣味を書き綴る。

vuedraggableを使って並び変えたリストをflaskに送る【Flask】【Vue.js】

はじめに

そもそもjavascriptを使ったことがほとんどなく

node.jsやnpmに関して、全く知識がなかったため、

Flaskでそれらを使わずにVue.jsを使いたかったために

その方法を四苦八苦したので、忘れないようにメモしておきます。

コードはより良い方法があったり、実践環境で使うにはアレかもしれません。

とりあえず、動くことを目標に作りました。

私の環境ではIDEにpycharmを使っているので、

javascriptライブラリはローカルに保存されて、便利です。

完成図

f:id:hibari2978:20190713161053g:plain

コード

全体コードです。

list_move.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" type="text/css" href="../static/css/list_move.css">
    <script src="../static/js/vue.min.js"></script>
    <script src="//cdn.jsdelivr.net/npm/sortablejs@1.8.4/Sortable.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>

<body>
    <div id="app">
        <form v-on:submit.prevent="submit">
            <draggable v-model="list.list_id" element="ul" :options="{animation:400}">
                <li v-for="item in list.list_id" :key="item.id" class="input_list">[[ item.id ]]</li>
            </draggable>
            <input type="submit" value="submit">
        </form>
            <div v-if="display">
                <h2>ResultList</h2>
                <ul>
                    <li v-for="item in result_list" class="output_list"> [[ item.id ]] </li>
                </ul>
            </div>
    </div>
</body>

<script>
    new Vue({
        el: '#app',
        delimiters: ['[[', ']]'],
        data: {

            list: {
                list_id:[
                    { id: 1 },
                    { id: 2 },
                    { id: 3 },
                    { id: 4 },
                    { id: 5 },
                    { id: 6 },
                    { id: 7 }
                ]
            },
            display: false,
            result_list: []

        },
        methods :{
           submit: function() {
               axios.post('/api', this.list)
                    .then(response => {
                        this.result_list = response.data.result_list;
                        this.display = true;
                    })
                    .catch(error => {
                        console.log(error);
                    })
            }
        }
    })
</script>

app.py

from flask import Flask, request, render_template, send_file, jsonify
import os

app = Flask(__name__)


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

@app.route('/api', methods = ['POST'])
def get_list_data():
    data_list = {
        "result_list": request.json["list_id"]
    }
    return jsonify(data_list)

Vue.jsのdelimiters

Flaskの標準テンプレートエンジンであるJinja2との共存を防ぐために、

delimitersを{{ }}から へと変更します。

delimiters: ['[[', ']]']

注意!

ここでハマったのが、開発バージョンではdelimitersが効いてないようです。

こちらのドキュメントでは"完全ビルドでのみ利用可能"とあります。 API — Vue.js

はじめに — Vue.js こちらの本番バージョンのことであるのか、分かりませんが

開発バージョンではなく、本番バージョンを使うと動作しました。

npmを使わずにvuedraggableを使う

リストをマウスで並び替えられるvuedraggable。

使用方法を検索しても、ほとんどnpmを使ったものばかりで、苦戦しました。

まず

<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.8.4/Sortable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Vue.Draggable/2.20.0/vuedraggable.umd.min.js"></script>

で、必要なライブラリをimportします。

Vueのデータをとりあえず、こんな風に設定します

 data: {
            list: {
                list_id:[
                    { id: 1 },
                    { id: 2 },
                    { id: 3 },
                    { id: 4 },
                    { id: 5 },
                    { id: 6 },
                    { id: 7 }
                ]
            }
}

HTMLにはlist_idのidを表示させ、並び替えられるようにします。

 <draggable v-model="list.list_id" element="ul" :options="{animation:400}">
        <li v-for="item in list.list_id" :key="item.id" class="input_list">[[ item.id ]]</li>
 </draggable>

これでlistを並び替えられるようになりました。

Vue.jsのDataをFlaskに送信

こちらを参考にしました。

kivantium.hateblo.jp

まず、htmlでaxiosをimportします

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

htmlのformはこんな感じで、先ほどのリストを入れ子にしています。

<form v-on:submit.prevent="submit">
    <draggable v-model="list.list_id" element="ul" :options="{animation:400}">
         <li v-for="item in list.list_id" :key="item.id" class="input_list">[[ item.id ]]</li>
    </draggable>
    <input type="submit" value="submit">
</form>

vueのmethodsに送信ボタンが押された時のメソッドを書きます。

methods :{
    submit: function() {
        axios.post('/api', this.list)
                 .then(response => {
                        this.result_list = response.data.result_list;
                        this.display = true;
                  })
                 .catch(error => {
                        console.log(error);
                 })
    }
}

これで送信ボタンが押されると、/apiにPostされるので

Flaskの方には、送信先のメソッドを作ります。

@app.route('/api', methods = ['POST'])
def get_list_data():
    data_list = {
        "result_list": request.json["list_id"]
    }
    return jsonify(data_list)

request.jsonで送信されたjsonファイルが参照できるので、

それを色々活用できるかと思います。