はじめに
フロントエンドで全部できるっちゃできるけど、やっぱり計算部分にPythonの楽さは欲しいなあ、という思いからサーバでプログラムを動的に動かすCGIを触ってみたのでそのまとめ。バックエンドは未だ疎い。
フリーレンタルサーバーのXREAのアカウントを持っているので実際にそこで試してみる。
無料から使える高機能・高品質レンタルサーバー | XREA(エクスリア)
やりたいことは、
- ボタンをクリック
- Vue.jsとaxiosを使ってデータをサーバに渡す
- Pythonで書かれたCGIスクリプトを実行して演算、結果をJSONで返す
- 同じ画面に返されたデータを表示
というかんじ。
今回は例として入力された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
ってなんぞやと思ったら object
の o
らしい...
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だとここ。
Context-Type
指定の行の後の print()
は改行のためで、これを入れないとダメな仕様みたい。 普通に Context-Type
文字列の最後に \n
してもOK。
アップロード後はCGIスクリプトを入れたディレクトリとそのファイルのパーミッションを指定する必要があり、XREAにも推奨パーミッションが書いてある。
特に、CGIの実行ファイルは700以上(実行可能)にする必要があるのは注意(よく忘れた)。
以上のXREAの仕様が書いてあるリンクも貼っておく。
仕様 | 無料から使える高機能・高品質レンタルサーバー | XREA(エクスリア)
実行
ファイルを上げて実際に試してみた画面がこちら
いいかんじ。空欄や小数で送信したら普通にエラーになるけど、まあお試しなので。
以上。