質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

2回答

346閲覧

AJAXでPythonからのデータを受け取ることができない

numin

総合スコア37

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

1グッド

1クリップ

投稿2025/04/23 03:30

編集2025/04/23 04:42

実現したいこと

HTMLで作成したページから簡単に単位変換を行うことのできる仕組みを、AJAX/CGI(Python)で作りたいと考えています。

前提

現在、下記のようなプログラムのプロトタイプを作成しています。

  1. HTMLのform要素で入力された(プロトタイプでは自動設定)変換前数値・変換前単位・変換後単位をAJAXからPythonファイルへ渡す
  2. 渡された値を基にpintライブラリを用いて単位変換を実行、結果を出力する
  3. 出力された結果をAJAXで受け取り、指定したP要素内に表示

ただ何故か出力結果が毎回正しく表示されず、困ってしまっています。

※なおAJAXについては初心者なので、見当違いなコードになってしまっていたら申し訳ありません。

発生している問題・エラーメッセージ

ブラウザのコンソール上に問題は出力されていないようです。

P要素の表示は毎回[object Object]となります。

該当のソースコード

index.html

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4<meta charset="UTF-8"> 5<meta name="viewport" content="width=device-width, initial-scale=1.0"> 6<title>Unit Converter Test</title> 7<script src="jquery-3.6.0.min.js"></script> 8</head> 9<body> 10<main> 11<h1>Unit Converter</h1> 12<br> 13<form id="converter" name="converter" method="post"> 14<label for="num">変換前の数値を入力:</label> 15<input type="number" id="num" name="num"> 16<br> 17<label for="before">変換前の単位を選択:</label> 18<input type="text" id="before" name="before" value="cm"> 19<br> 20<label for="after">返還後の単位を選択:</label> 21<input type="text" id="after" name="after" value="in"> 22<br> 23<input type="button" id="submit_btn" value="送信" onclick="post_with_ajax()"> 24</form> 25<p id="result-area"></p> 26 27</main> 28<script> 29function post_with_ajax() { 30let formData = $('#converter'); 31$.ajax({ 32type: "post", 33url: './converter.py', 34data: formData.serialize(), 35}).done(function(data){ 36document.getElementById('result-area').textContent = data; 37}).fail(function(data){ 38document.getElementById('result-area').textContent = data; 39}); 40} 41</script> 42</body> 43</html>

converter.py

Python

1#!/usr/local/bin/python3.7 2 3import cgi 4import pint 5 6storage = cgi.FieldStorage() 7print('Status: 200 OK') 8print('Content-Type: text/html\n') 9 10ureg = pint.UnitRegistry() 11 12try: 13 value = float(storage.getvalue('num')) 14 from_unit = storage.getvalue('before') 15 to_unit = storage.getvalue('after') 16 17 # Create quantity with unit 18 quantity = value * ureg(from_unit) 19 20 # Perform conversion 21 converted = quantity.to(to_unit) 22 23 # Output result 24 print(f"\n{value} {ureg(from_unit).units:~} = {converted.magnitude:.2f} {converted.units:~}") 25 26except pint.errors.UndefinedUnitError: 27 print("Error: One or both of the units are not recognized.") 28except pint.errors.DimensionalityError: 29 print("Error: The units are not compatible for conversion.") 30except ValueError: 31 print("Error: Invalid numeric input.") 32except Exception as e: 33 print(f"An unexpected error occurred: {e}") 34

試したこと

Pythonコード/ライブラリに問題があるのかと考え、下記のようなテストプログラムを作成しSSH経由で実行しましたが、結果は問題なく出力されているようでした。

Python

1import pint 2 3print('Status: 200 OK') 4print('Content-Type: text/html\n') 5 6ureg = pint.UnitRegistry() 7 8try: 9 value = 10.0 10 from_unit = 'cm' 11 to_unit = 'in' 12 13 # Create quantity with unit 14 quantity = value * ureg(from_unit) 15 16 # Perform conversion 17 converted = quantity.to(to_unit) 18 19 # Output result 20 print(f"\n{value} {ureg(from_unit).units:~} = {converted.magnitude:.2f} {converted.units:~}") 21 22except pint.errors.UndefinedUnitError: 23 print("Error: One or both of the units are not recognized.") 24except pint.errors.DimensionalityError: 25 print("Error: The units are not compatible for conversion.") 26except ValueError: 27 print("Error: Invalid numeric input.") 28except Exception as e: 29 print(f"An unexpected error occurred: {e}") 30input() 31

補足情報(FW/ツールのバージョンなど)

環境はLolipopレンタルサーバ内、Pythonのバージョンは3.7です。

追記(2025/4/23 13:40)

converter.pyを直接ブラウザで開いたところ、Internal Error 500 が出力されてしまいました。

なおPythonの参照先は以前に作成したCGI と同一、パーミッションも700となっているのでこちらの問題とはあまり関係がないかと思います。


以上です。

ご教示いただけますと幸いです。

よろしくお願いいたします。

melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yambejp

2025/04/23 03:48

jqueryはマストですか?
numin

2025/04/23 04:04

コメントを頂きありがとうございます。 不慣れなAJAXに関する解説記事の殆どでJqueryを使用していたためそのまま使っている状況ですが、ネイティブなJavaScriptでも実装可能でしたら方法にはこだわっていません。 よろしくお願いいたします。
melian

2025/04/23 05:56 編集

※ 削除
numin

2025/04/23 04:45

コメントいただきありがとうございます。 教えていただいた点を踏まえると、そもそもこのようなリクエストをAJAX経由でやり取りすること自体が不可能ということになるのでしょうか。 よろしくお願いいたします。
melian

2025/04/23 06:12 編集

度々すみません、Python 3.12.7 で以下の様にして簡易の HTTP サーバを起動して確認してみました。例えば、変換前の数値として 10 を入力して送信ボタンをクリックすると、ブラウザの画面に「10.0 cm = 3.94 in」が表示されます。(すみません、cgi.FieldStorage()でJSON形式のPOSTデータを扱うことができました) $ python3 -m http.server --cgi ファイルの配置の以下の通りです。 $ tree . . ├─ cgi-bin │ └─ converter.py └─ index.html 変更点は index.html の post_with_ajax() 関数内の URL です。 url: './converter.py', => url: './cgi-bin/converter.py', ただ、cgi モジュールは、Python 3.13 から非推奨で、将来的に削除されるとのことです。 > DeprecationWarning: 'cgi' is deprecated and slated for removal in Python 3.13
numin

2025/04/23 06:23

検証していただきありがとうございます。 こちらでもフォルダ構成を合わせてみたのですが、変わらず... そうなると、やはり環境・設定のせいなのでしょうか。 現状、 cgi-bin(755) ■converter.py(700) index.html というフォルダ/パーミッションになっています。 よろしくお願いいたします。
melian

2025/04/23 06:32

> そうなると、やはり環境・設定のせいなのでしょうか。 はい、その可能性が高いかと思います。例えば、ウェブサーバとして Apache をご利用でしたら、以下のドキュメントを参照して設定を確認してみてください。 Apache Tutorial: CGI による動的コンテンツ - Apache HTTP サーバ バージョン 2.4 https://httpd.apache.org/docs/2.4/ja/howto/cgi.html
numin

2025/04/23 10:59

melianさん、度々コメントを頂きありがとうございました。 今回利用しているレンタルサーバとは別に契約しているVPSで事前設定・コード移行を実行したり、その後コードを限界まで単純化してからレンタルサーバに戻したりといたことを繰り返していたところ、Lolipopでは何故かtry/except文が正しく実行されていないことがわかりました。 該当のコードを消してシンプルな指示に変えたところ、無事実行することができました。 つきましては一番丁寧にご説明・ご検証していただいたmelianさんのコメントをベストアンサーに選ばせていただきたいのですが、改めて解答欄に投稿していただくことは可能でしょうか。 何卒よろしくお願いいたします。
melian

2025/04/23 11:14

問題が解決できてよかったです。最初、私の方で色々と勘違いをして的外れなコメントをしてしまいました。ベストアンサーには程遠いので、 numin さんの自己回答・BAの方が良いかと思います。よろしくお願いします。
numin

2025/04/23 23:38

承知しました、それでは自己回答とさせていただきたいと思います。 コメント・回答を頂いた皆様、ありがとうございました。
guest

回答2

0

自己解決

コメント・回答欄でご助言いただいた皆様、ありがとうございました。

コメントにて「環境/設定に問題があるのかもしれない」とのアドバイスを頂き複数のVPS/レンタルサーバで検証を行ったところ、原理までは解らないものの、原因となっているコードが判明し無事プログラムを実行できるようになりました。

問題を起こしていた箇所

検証した限りVPSでは発声せずLolipopのレンタルサーバのみで問題を起こしていたようなのですが、try/except文を使うことにより500 Internal Errorが引き起こされてしまっていたようです。

下記コードの通り該当箇所を削除しより単純な指示に変更したところ、問題なく動作しました。

修正後のPythonコード

#!/usr/local/bin/python3.7 import cgi import pint form = cgi.FieldStorage() ureg = pint.UnitRegistry() value = float(form.getvalue('num')) from_unit = form.getvalue('before') to_unit = form.getvalue('after') # Create quantity with unit quantity = value * ureg(from_unit) # Perform conversion converted = quantity.to(to_unit) # Output result print("Content-Type: text/html\n") print(f"\n{value} {ureg(from_unit).units:~} = {converted.magnitude:.2f} {converted.units:~}")

※HTMLのソースコードには変更を加えていません。また一部変数名やprintの方法などを解りやすいよう変更しています。


以上です。

ご協力いただきありがとうございました。

投稿2025/04/23 23:51

numin

総合スコア37

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

とりあえずpostデータの受け渡しについて

html

1<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script> 2<script> 3$(function(){ 4 $("#btn").on("click",function(){ 5 $.ajax({ 6 url:<apiを指定>, 7 type:"post", 8 dataType:"text", 9 data:new FormData($("#form")[0]), 10 cache:false, 11 processData: false, 12 contentType: false, 13 }).done(function(data){ 14 console.log(data); 15 }); 16 }); 17}); 18</script> 19<input type="button" value="test" id="btn"> 20<form id="form"> 21<input name="hoge" value="1"> 22</form>

同様のことをjQueryを使用しない場合はこう

html

1<script> 2document.addEventListener('click',()=>{ 3 fetch(<apiを指定>,{method:'post',body:new FormData(document.querySelector('#form'))}) 4 .then(res=>res.text()) 5 .then(data=>console.log(data)); 6}); 7</script> 8<input type="button" value="test" id="btn"> 9<form id="form"> 10<input name="hoge" value="1"> 11</form>

注意

それぞれAPIが返すデータ形式によって受け取り方を変える必要があります
jQueryであればdataTypeを"json"に変更するなど、vanillaであればres=>json()を噛ませるなど

投稿2025/04/23 04:06

編集2025/04/23 04:17
yambejp

総合スコア117654

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

numin

2025/04/23 04:38

教えていただきありがとうございます。 返されるデータの型が重要なんですね...。 何分不慣れなもので、現状に適用してテストするのに時間がかかってしまいそうですが、検証してみたいと思います。
yambejp

2025/04/23 05:05

基本的に $('#converter')をシリアライズするところがおかしいと思います。 postする前提であれば値はFormDataで作成し、getするならURLSearchParamsを使います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問