« Bash on Ubuntu on Windows -- WindowsとUbuntuの連携機能を使ってみる | トップページ | 嫁と格安SIM − mineoの場合 − (その7) »

2017.02.05

jQueryとPython間におけるJSONPを用いたやりとり

JavaScriptを勉強中なのですが、サーバサイドのcgiとの間でのJSONPを利用した通信について、サンプルプログラムとしてサーバサイドcgiをpythonで作ったのですが、JSONPの仕組みを調べながら進めたところ、結構手間取ったので、メモ。

jQuery + PythonのJSONでのデータのやり取り:satomacoto
にあるサンプルプログラムを参考にに作ってみました。ありがとうございます。

JSONPで悩むある程度の人々へ:tsujimotter
JSONPの原理が分かりやすく解説されています。ありがとうございます。

index.htmlにフォームを記述して、jQuery及びJavaScriptを読み込みます。jQueryはjquery-3.1.1.min.jsを使用。
リンクをクリックすると、submit, clearできるようにし、結果を<div id="baz"></div>領域に出力します。


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQueyr + Python</title>
</head>
<body>
<h1>jQuery + Python</h1>
<form id="hoge">
<input type"text" name="foo" />
<input type"text" name="bar" />
<input type"text" name="baz" />
</form>
<!- ->
<a id="foo" href="#">show</a>
<a id="bar" href="#">clear</a>
<div id="baz"></div>
<!- ->
<script type="text/javascript" src="lib/jquery/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="sample.js"></script>
<!- ->
</body>
</html>

sample.jsは以下のとおり。


function p2j(d) {
if (d.constructor != Array) {
return d;
}
var data = {};
for (var i = 0; i < d.length; i++) {
data[d[i].name] = d[i].value;
}
return data;
};
<!- ->
$(document).ready(function () {
$('#foo').click(function () {
var query = p2j($(":input").serializeArray());
console.log(query);
$.getJSON('[url]/sample.py?callback=?', query)
.done(function (data) {
var html = "";
for (var i in data) {
html += data[i].key + ':' + data[i].value + ' ';
}
$('#baz').html(html);
})
.fail(function () {
window.alert('正しい結果を得られませんでした。');
});
});
$('#bar').click(function () {
$('#baz').html('');
});
});

[url]にはsample.pyのurlを記入して下さい。

sample.pyは以下のとおり。python 3.5.2で試しましたが、python 2.7系でも動くと思います。


#!/usr/bin/env python
# coding: utf-8
#
import cgi
import cgitb; cgitb.enable()
import json
#
print ("Content-type: application/javascript; charset=utf-8\n\n")
#
form = cgi.FieldStorage()
#
foo = form.getfirst("foo", "")
bar = form.getfirst("bar", "")
baz = form.getfirst("baz", "")
#
callback = form.getfirst('callback', "callback")
#
print ('%s(%s)' % (callback, \
json.dumps([{'key':'foo','value':foo}, \
{'key':'bar','value':bar}, \
{'key':'baz','value':baz}], \
sort_keys=True, indent=4)))

sample.jsでは、input領域をjQueryのserializeArrayでシリアライズしてdata(query)に連想配列化し、$.getJSONのURLの後の引数とします。URLには、callback=?が付加されており、?にjQueryがcallback関数名を埋め込みます。通信が成功するとdone配下の即時関数を実行し、失敗するとfail配下の即時関数が実行されてエラーメッセージのポップアップを表示します。

Python CGIである、sample.pyでは、各フィールド名と値を取得してjson形式にし、先にjQueryが埋め込んだcallback関数名で包んで返します。この関数名はsample.py内でcallbackの値として取得できます。

sample.pyは、例えば、テキストボックスfooに'AB'、barに'CD'、bazに'EFG’が入力されている場合、
[url]/sample.py?callback=jQuery31109404937469658704_1486278348536&foo=AB&bar=CD&baz=EFG&_=1486278348537
のように、呼び出されます。最後の変数'_'は呼び出されるごとにインクリメントされます。

(2017.02.11追記)
sample.pyをJSONとJSONPの両方に対応できるように改造しました。

sample.py(共用)は以下のとおり。


#!/usr/bin/env python
# coding: utf-8
#
import cgi
import cgitb; cgitb.enable()
import json
#
form = cgi.FieldStorage()
#
foo = form.getfirst("foo", "")
bar = form.getfirst("bar", "")
baz = form.getfirst("baz", "")
#
r = json.dumps([{'key':'foo','value':foo}, \
{'key':'bar','value':bar}, \
{'key':'baz','value':baz}], \
sort_keys=True, indent=4)
#
if 'callback' in form:
callback = form.getfirst('callback', "callback")
print ("Content-type: application/javascript; charset=utf-8\n\n")
print ('%s(%s)' % (callback, r))
else:
print ("Content-type: application/json; charset=utf-8\n\n")
print (r)

引数中の'callback'有無で判別しています。

JSONPを使った例:
index.html


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuey + Python (JSONP)</title>
</head>
<body>
<h1>jQuery + Python (JSONP)</h1>
<form id="hoge">
<input type"text" name="foo" />
<input type"text" name="bar" />
<input type"text" name="baz" />
</form>
<!- ->
<a id="foo" href="#">show</a>
<a id="bar" href="#">clear</a>
<div id="baz"></div>
<!- ->
<script type="text/javascript" src="lib/jquery/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="sample.js"></script>
<!- ->
</body>
</html>

sample.js


function p2j(d) {
if (d.constructor != Array) {
return d;
}
var data = {};
for (var i = 0; i < d.length; i++) {
data[d[i].name] = d[i].value;
}
return data;
};
<!- ->
$(document).ready(function () {
$('#foo').click(function () {
var query = p2j($(":input").serializeArray());
console.log(query);
$.getJSON('[url]/sample.py?callback=?', query)
.done(function (data) {
var html = "";
for (var i in data) {
html += data[i].key + ':' + data[i].value + ' ';
}
$('#baz').html(html);
})
.fail(function () {
window.alert('正しい結果を得られませんでした。');
});
});
$('#bar').click(function () {
$('#baz').html('');
});
});

JSONを使った例:
index2.html


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuey + Python (JSON)</title>
</head>
<body>
<h1>jQuery + Python (JSON)</h1>
<form id="hoge">
<input type"text" name="foo" />
<input type"text" name="bar" />
<input type"text" name="baz" />
</form>
<!- ->
<a id="foo" href="#">show</a>
<a id="bar" href="#">clear</a>
<div id="baz"></div>
<!- ->
<script type="text/javascript" src="lib/jquery/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="sample2.js"></script>
<!- ->
</body>
</html>

sample2.js


function p2j(d) {
if (d.constructor != Array) {
return d;
}
var data = {};
for (var i = 0; i < d.length; i++) {
data[d[i].name] = d[i].value;
}
return data;
};
<!- ->
$(document).ready(function () {
$('#foo').click(function () {
var query = p2j($(":input").serializeArray());
console.log(query);
$.getJSON('./sample.py', query)
.done(function (data) {
var html = "";
for (var i in data) {
html += data[i].key + ':' + data[i].value + ' ';
}
$('#baz').html(html);
})
.fail(function () {
window.alert('正しい結果を得られませんでした。');
});
});
$('#bar').click(function () {
$('#baz').html('');
});
});

(2017.02.11追記ここまで)

|

« Bash on Ubuntu on Windows -- WindowsとUbuntuの連携機能を使ってみる | トップページ | 嫁と格安SIM − mineoの場合 − (その7) »

パソコン・インターネット」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1024423/69486779

この記事へのトラックバック一覧です: jQueryとPython間におけるJSONPを用いたやりとり:

« Bash on Ubuntu on Windows -- WindowsとUbuntuの連携機能を使ってみる | トップページ | 嫁と格安SIM − mineoの場合 − (その7) »