LoginSignup
5
6

More than 1 year has passed since last update.

【CGI】Vue.js + axiosでサーバのPythonプログラムを動かし出力データをもらう

Last updated at Posted at 2019-12-21

はじめに

フロントエンドで全部できるっちゃできるけど、やっぱり計算部分にPythonの楽さは欲しいなあ、という思いからサーバでプログラムを動的に動かすCGIを触ってみたのでそのまとめ。バックエンドは未だ疎い。

フリーレンタルサーバーのXREAのアカウントを持っているので実際にそこで試してみる。
無料から使える高機能・高品質レンタルサーバー | XREA(エクスリア)

やりたいことは、

  1. ボタンをクリック
  2. Vue.jsとaxiosを使ってデータをサーバに渡す
  3. Pythonで書かれたCGIスクリプトを実行して演算、結果をJSONで返す
  4. 同じ画面に返されたデータを表示

というかんじ。

今回は例として入力された2数の最大公約数と最小公倍数を計算して返すプログラムを作る。

作ってみる

ファイルの配置

├─ cgi-bin
│    └─ index.cgi
├─ index.html
└─ main.js

Pythonで書かれたCGIスクリプトは cgi-bin というディレクトリを作ってその中に投入。Pythonで書かれてるけど拡張子は .cgi

サーバにアップロードした後、CGIまわりのパーミッションを指定する必要があるけどそれは後述。

HTML (index.html)

<html>
<head>
    <meta charset="UTF-8">
    <title>最大公約数と最小公倍数を返す</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script type="module" src="main.js"></script>
</head>
<body>
    <div id="app">
        <!-- 入力部分 -->
        <p>
            <input v-model="a" type="number" value="12">
            <input v-model="b" type="number" value="15">
            <button v-on:click="getResult">計算</button>
        </p>
        <!-- 表示部分 -->
        <p>
            最大公約数: {{ result['gcd'] }}<br>
            最小公倍数: {{ result['lcm'] }}
        </p>
    </div>
</body>
</html>

CDNでVue.jsとaxiosを読み込んでおく。
Vueで書いたJavaScriptのファイルは type="module" で読み込むと、DOMが読み込まれた後に実行されるので安心。

JavaScript (main.js)

var vm = new Vue({
    el: '#app',
    data: {
        a: 12,
        b: 15,
        result: {},  // 返ってきたオブジェクトを格納する変数
    },
    methods: {
        getResult: function() {
            const url = './cgi-bin/';
            // axiosでデータの受け渡し
            axios.get(url, {
                params: {  // paramsでパラメータを指定
                    a: this.a,
                    b: this.b
                }
            })
            .then(res => this.result = res.data)  // データをresultに格納
        }
    }
});

Vueインスタンスを作ってaxiosでデータの受け渡しをする。
URLは ./cgi-bin/index.cgi という名前ならHTML同様ファイル名を指定しなくてもOKなもよう。

また、返ってくるデータ res.data はオブジェクトとして取り出せるので JSON.parse() とかで直す必要がなかった。(JSONにして返したんだからJSON文字列で返ってくるだろうという思い込みにやられた。)
ちなみにやるとこんなエラーが出る。

SyntaxError: Unexpected token o in JSON at position 1

o ってなんぞやと思ったら objecto らしい...

Python CGI (index.cgi)

#!/usr/local/bin/python3
# -*- coding: UTF-8 -*-
import cgi
import cgitb
import math
import json

cgitb.enable()  # CGIのデバッグをオン

form = cgi.FieldStorage()  # GETで得たデータを格納
a = int(form['a'].value)   # データは文字列でやってくるので数値に変換
b = int(form['b'].value)

data = {
    'gcd': math.gcd(a, b),  # math.gcd() は Python 3.5 で追加されたらしい
    'lcm': a * b // math.gcd(a, b)
}

print('Content-Type: application/json')
print()
print(json.dumps(data))  # json形式にして返す

行頭でPythonのインタプリタの場所を指定。レンタルサーバの仕様ページに各言語のCGIの実行パスが書いてあると思うので確認する。XREAだとここ。
xrea_py_path.png

Context-Type 指定の行の後の print() は改行のためで、これを入れないとダメな仕様みたい。 普通に Context-Type 文字列の最後に \n してもOK。

アップロード後はCGIスクリプトを入れたディレクトリとそのファイルのパーミッションを指定する必要があり、XREAにも推奨パーミッションが書いてある。
xrea_permission.png
特に、CGIの実行ファイルは700以上(実行可能)にする必要があるのは注意(よく忘れた)。

以上のXREAの仕様が書いてあるリンクも貼っておく。
仕様 | 無料から使える高機能・高品質レンタルサーバー | XREA(エクスリア)

実行

ファイルを上げて実際に試してみた画面がこちら
xrea_cgi_disp.png
いいかんじ。空欄や小数で送信したら普通にエラーになるけど、まあお試しなので。

以上。

5
6
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
5
6