Python/Djangoを使って、機械学習を使ったプログラムを作成中で、その中でAjaxの実装と、Ajaxでサーバーから受け取った配列の処理方法がようやくできたので、備忘録として記録しておく。
Ajaxの実装 – jQuery –
jQueryの書き方自体はまだ勉強中だが、Ajaxの実装方法はなんとなくわかった気がする。(jQueryやAjax設定について「もっとこうしたほうがいい」みたいなご意見があれば、ぜひよろしくお願いいたします。)
$("form").submit( function(event){
event.preventDefault();
// ↑ここでDjangoのformのデフォルト操作を一時的に防止しているらしい
var form = $(this);
// ↓ここからがAjaxの設定
$.ajax({
url: form.prop("action"), // htmlの中のformタグのaction属性に処理を行うファイルと紐付けているurlを指定。
method: form.prop("method"), // urlと同様formタグのmethod属性にデータ通信の方法を指定。今回は"POST"を指定している場合を想定。
// type: "POST" ←こんな感じでHTTPリクエストの種類指定もできる
data: new FormData($("#form").get(0), //ここでformタグに格納されている情報を、変数dataに入れてサーバー側に送信
# type
dataType: "json",
// サーバーから受け取るレスポンスのデータ形式を指定。
// 指定できるのは、html, text, xml, json, script, jsonp
// dataType: 'json text'のような形で、想定される形式を複数指定することもできるみたい。
processData:false,
// ここがtrueだと、dataに指定した値を文字列に変換する処理を行う。今回のようにformタグのデータを送信する場合、formタグのhtmlが文字列として送られていた。
contentType:false,
beforeSend: function(xhr, settings){
// beforeSendでリクエストを送る前の処理を記述する。
// CSRF Tokenの設定や前の結果を削除などが可能
xhr.setRequestHeader("X-CSRFToken", $("input[name='csrfmiddlewaretoken']").val());
// $(HTML要素).empty()→これで前の結果の削除などができる。
},
})
// ↓Ajaxでデータを送り、Pythonで処理を行ってデータが返ってきたあとに実行される部分
// サーバーから返ってきたデータが変数dataに格納される。
.done( function(data){
alert("done");
// 処理
})
// ↓ここでAjax処理に失敗した場合にコンソールにlogを出力するように設定している。
.faile(function(jqXHR, textStatus, errorThrown){
jqXHR + "\n" + textStatus + "\n" + errorThrown);
});
});
<参考>
トップに戻るPythonでサーバーからJSON形式で返す
Pythonプログラムの方で処理を行った後、結果をJSON形式で返す。
from django.http import JsonResponse
import sample
results = sample() # sample()の部分は処理を行うpythonプログラム。今回は、処理結果を辞書型で返すことを想定。
# 例:{"test1":"yamada", "test2":"tanaka"}
return JsonResponse(
data = results,
#safe = False,
)
JsonResponseで返す中身は、こんな感じ↓。Pythonの処理結果でなくても、JSONファイルとして送信することも可能。
[
{
"name":"田中",
"age":20
},
{
"name":"山田",
"age":30
}
]
ちなみに、そもそもJSONって何?ってとこもメモしておく。
そもそもJSONとは
JavaScript Object Notation(JSON、ジェイソン)はデータ記述言語の1つである。軽量なテキストベースのデータ交換用フォーマットでありプログラミング言語を問わず利用できる[1]。名称と構文はJavaScriptにおけるオブジェクトの表記法に由来する。
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation
参考:【初心者向け】JSONファイルとは何か?jsonファイルの構造と使い方を実例でわかりやすく解説
最初、JSON形式って、Pythonの辞書型と同じじゃないか!と思っていたが、Pythonの辞書型とJSONは全く違うものであることがだんだんわかってきた。
Pythonの辞書型→データ型。例えば、Pythonでは文字列ならstr型、整数ならint型、とデータの型があり、辞書型は、その中でdict型、と呼ばれるデータの型であり、キーと値が格納され、取り出したり、保存したりできる。
JSON→データフォーマット。例えば、CSVだと、カンマ区切り、というルールに基づいてデータが保存されている。JSONもこれと同様で、データを{}で囲む、文字列は””で囲む、といったルールを持つデータフォーマット。したがって、JSON形式のファイルを読み込んで、辞書型のようにキーを指定して値を取り出す、というような作業は基本的にはできない。たとえば、Pythonの辞書型に変換して初めて取り出しができるようになる。なぜなら、言ってしまえば、JSON形式に保存されている上記のようなデータは、「ただの文字列」とも言えるものだから。
この辺のPython辞書型とJSONの違いについては他にもわかりやすく、かつ詳しく書かれている方がいらっしゃるので、そちらも参考に。
JSON形式データを受け取って処理
Pythonでの処理のあと、JSON形式でResponseを返せたら、HTML側で受け取ったデータを元に処理を行う。
処理を追加する箇所は、Ajaxの設定のところで書いた下記の部分。
// ↓Ajaxでデータを送り、Pythonで処理を行ってデータが返ってきたあとに実行される部分
// サーバーから返ってきたデータが変数dataに格納される。
.done( function(data){
alert("done");
// 処理
})
例えば、今回のようにPythonの辞書型をJSON形式で返した場合、for文を使って次のように値を取り出すことが可能。
.done( function(data){
alert("done"); //ここはあってもなくてもいい。Responseを受け取ったら、doneという通知が出るようにしているだけ。
var array = [];
for(var i = 0; i < data.length; i++){
array.push({
"test1":data[i].test1,
"test2":data[i].test2,
// この部分で、配列arrayに、連想配列(辞書)を格納している。
});
}
// 配列arrayに格納した連想配列を次のようなfor文で取り出し、HTMLに飛ばすことが可能。
var test1 = array[0]["test1"]
var test2 = array[0]["test2"]
// ↓ここは、適宜受け取ったデータを飛ばしたいHTMLのclassやid, CSSセレクタなどを指定
$('#HTMLのid').children('#子要素のid').text(test1)
$('#HTMLのid').children('#子要素のid').text(test2)
<参考>
まとめ
と、こんな感じで、PythonとJSON形式を用いてAjaxを実装することができた。
元々は、Pythonで処理結果を辞書型かリストで返したものがうまく受け取れず、どうしたものかと思ってたどり着いた方法で、もしかしたらもっと効率よく少ない行数で同じ処理を実行する方法があるのかもしれない…。
ただ、少なくとも今回のようなコードを書くことで、例えば、Pythonで機械学習の画像処理を用いて、アップロードした画像の類似画像トップ3をデータベースの中から選んでAjaxで表示する、みたいなコードを書くことができ、例えば、似ている芸能人トップ3、みたいなアプリを作ったりすることもできると思う。
今日はこんな感じで。もっと良い書き方や「ここの理解間違ってる」というような指摘がございましたら、(優しく)ご指摘いただけると幸いです。
(その他参考) プログラミング備忘録等
コメント