久しぶりにjQueryのAjaxを用いてPython CGIとJSONフォーマットでのデータのやり取りを実装しようとしたが,思いの外詰まってしまったのでメモ.

<!DOCTYPE html>
<html lang=ja>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>AjaxPythonCGI</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
  </head>
  <body>
    <div class="container-fluid">
      <div class="row">
        <div class="col-sm-12 col-md-12">
          <h1 class="text-center">Click below button to send sample text</h1>
          <button type="button" class="btn btn-default btn-lg pull-right" id="button">Send</button>
        </div>
      </div>
      <div class="row">
        <div class="col-sm-12 col-md-12">
          <textarea class="form-control" rows="2" placeholder="Received text is show here" id="result" disabled></textarea>
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
    <script src="js/sample.js"></script>
  </body>
</html>
index.html
#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import json

print("Content-type: application/json")
print("\n\n")

data = sys.stdin.read()
params = json.loads(data)
text = params['text']


result = {'text': text}

print(json.JSONEncoder().encode(result))
print('\n')
sample.cgi
$(window).load(init());

function init() {
  console.log("init");
  $("#button").click(function() {
    console.log("clicked");
    var text = "Sample text";
    send(text);
  });
}

function send(text) {
  console.log(text);
  var json = JSON.stringify({'text': text});
  
  $.ajax({
    type: 'POST',
    url: 'cgi/sample.cgi',
    contentType: 'application/json',
    data: json,
    success: function(data) {
      console.log(data);
      console.log(data.text);
      $('#result').empty();
      $('#result').val(data.text);
    }
  });
  
  return false;
}
sample.js

index.htmlで用意したSendボタンを押すことでsample.jsにおいてイベントが発火し,text変数にSample textを入れた後,send()が呼ばれてこの変数をJSONフォーマット化してAjaxでsample.cgiに送る.

sample.cgiはPython3で書かれたCGIファイルだが,送られてきたデータをsys.stdin.read()で読み込み,json.loads()でJSONとしてロードする.その後JSONデータのKeyとしてsample.jsでJSONフォーマット化する際に設定したtextをここで指定し,データを読み出す.

Ajaxでsample.jsに返す際は,データを辞書で保存し,これをjson.JSONEncoder().encode()でJSONフォーマット化してprint()で送る.

返ってきたデータはsample.jsのsuccess: function()において引数として渡しているdataに入る.sample.cgiではデータを辞書で保存する際にKeyにtextを設定したため,ここでもdata.textとしてKeyを指定し,データを読み出す.

以上のように実装することで,Ajaxを用いてJSONデータをやり取りし,ページの動的な書き換えができる.